[security] Introducing signing support to MySensors
-
@Tibus You have to check the datasheet of ATSHA204A to see how it handles the datapin when not in use. I would recommend you have any analog cirquitry on dedicated pins though and keep one reserved for the ATSHA.
-
The "analog" pins can actually be used as digital IO pins.
-
@hek Not A6 and A7. They are pure analog.
-
Ok! That's new to me
-
@hek @tbowmo also found this the "hard" way. There are also some other forum discussions on the topic. It is basically how the AVR is designed.
-
Yeah. I put the led on A6 in the first revision of the micro board, and used 2 hours figuring out why the led wouldn't blink it's buried somewhere in the posts in my design thread.
-
I had this concerned from beginning. I will sound like a noon, but I am working on building a custom controller with loads of user configurable interface. For sake of my understanding is there any diagram or video or any resource regarding how to interface the ATSHA204A with arduino @Anticimex .
If there is something like that it will be of a great help. I am going to post a video soon of my work in progress app which controls the devices. I am also working on a scenario where someone can use the normal switches(existing ones) to operate the device and app will update accordingly. Still making way through the ACK part and the hops as I am using Ruby to do all the work
-
@mainali What do you mean? It is the simplest possible interface; one IO pin. You can see schematics in @tbowmo s "Minimal design thoughts" thread or my own GW design.
-
@mainali
Does this help you? Sometimes a few pics say more than a 1000 wordsI made this pic from the Datasheet giving you the pinouts of the ATSHA204A in all known housings.
And the way how to connect is (shamelessly stolen from the GW design of @Anticimex )
-
@sj44k @mainali Please note that that picture is incorrect. I have it connected to A3, not A7 (it is mentioned in the thread). Also note that in my design, I use a breakout board for ATSHA so the pin numbering on my breakout does NOT correspond to the SOT23-package.
-
Thanks a lot for all the Information
-
@Anticimex
Thanks for that info, to me it is clear that depending on the used pin in the software one should connect the ATSHA204A corresponding with the software.
Picture does show you being correct how simple it really is to embed the ATSHA204A hardware in the total setup.
-
@phil83
I fear you've already ordered the ATSHA204A ? I'm also in Germany so that would be easy.
If not - I'd take 10 pcs. They cost close to nothing -> nice@Anticimex
I don't agree with "This is an unlikely usecase because it is really no reason to sign sensor values. If you for some reason want to obfuscate sensor data, encryption is a better alternative."I think of Sensors used for Alarm-Systems. You need to trust the sensor reading because otherwise the attacker might jam the original Sensor and send his own Sensor data to let the alarm-system think the window is still closed (e.g.).
One more question: Are the Serials in the ATSHA in ascending order (i.e. when you have a reel of ICs is each S/N old S/N+1 ?) If this is the case, would it be possible to steal a keyfob to get a valid signing device, read the serial, use that S/N +1, sign the message and get still access to the garage door? I.e. do something one could call "S/N spoofing"? (I know that it is much easier to just break the garage door with a crowbar, but I'm intrested in this - at least hypotheticaly :))
Unfourtunately I don't have much time at the moment to try it out by myself, but I'm still really excited about your work and effort!
-
@Dirk_H The signing solution can be applied to both sensors and gateways. If you feel the need to have the gateway require signed messages from nodes, there is nothing to prevent it. I have already thought of that scenario and implemented support for it.
Regarding jamming, no security system can prevent that.
Regarding the generation of serials, you have to contact Atmel about that. And you still need to obtain the preshared key in order to generate properly signed messages. Neither the key nor the serial is ever sent over the air in clear text.
-
@Anticimex
Thank you very much for this solution.I think your solution is the best compromise, if you don't want to transmit more data.
The drawback is, that it isn't really as secure as AES 256 or above. It is a compromise.
What about a solution
- where the original message is untouched without a signature
- a consumer requests an AES 256 signature of this message, if he really needs it
- a second/third signature message is sent to the consumer with full AES 256 signature
In this solution, you could use different keys for different nodes and the risk of stolen keys would be minimized.
-
@FotoFieber
I think sha256 is pretty secure enough
Regarding splitting signature and message, I am not too fond of that, because it opens up a lot of attack vectors and it also put requirements on the sender to be able to retain a sent message. Potentially a lot of nodes sends data back and forth, so what happens if, for instance, the gateway sends a message to one node, then sends another message to another node, and then the first node sends a message requesting a signature on a message the gateway no longer has. We have to remember that ram memory is very limited so there are limits in what we can do with message management, unfortunately.
But all feedback is appreciated! Thanks!
-
@Anticimex
sha256 is secure enough. But if I understand the implementation correctly, you use the space at the end of the payload for the signature and not the full signature.Another thing to consider is that the strength of the signature is inversely proportional to the payload size.
If I calculate it right, the length of the signature is less or equal (23 bytes) 184 bit.
With a payload of 4 bytes, which would probably be the usual payload I have here, there would be left only 160 bit (20 bytes).
In comparison a HMAC_SHA256 uses 256 bit,
Or did I miss something?
It could be implemented quite simple:
- Node sends data to gateway which in my case is published to MQTT
- some consumer likes to have this signed and sends the node the message back with a sign request
- the node looks at the message and checks, if the value inside the message is still valid. When ok, it sends a HMAC splitted in two messages. If not, it ignores the message or sends NOK.
The problem with this implementation would be, that the node hast to be active to get the singing request.
Maybe it would be better to just send two other messages with the HMAC after the data.
I would suggest to implement the check of the HMAC where it is needed, not in the gateway, In my case, this would be node-red.
-
@FotoFieber
Regarding the weakened security based on the message size, you are correct.
But I still disagree on splitting the messages because it will mean that some messages will fail to be signed (depending on network load) and it is no good to have a solution that adds uncertainty in that respect. And I definitely do not want to add restrictions on which types of nodes are capable on signing and which are not. Having the gateway signing messages is a very real application in use cases like locks and such.
The opposite is also equally valid, some nodes might send "important" data. The gateway needs to be able to authenticate such nodes (keyfobs etc).
We have to weigh complexity vs resources, and currently we are pretty much at the limit of our capabilities. An ethernet or mqtt gateway running on an Arduino nano can today barely fit HW support for signing. SW signing does not fit. So we can't really get more complex with the solution without also stepping up the HW platform we execute on.
-
I should add that even if signature was separated in its own message, it still would not be full since the rf solution is only capable of sending 32 byte messages and some bytes are needed for routing info. So if "full" signature is required, some framing protocol will also be needed, and then things really get out of hand on a poor Arduino nano or pro mini.
I would suggest using RF69 with AES encryption if the signing scheme in place is inadequate.
-
Hi.
I am trying to design some boards. And I would like to have a little precision.
If I understand right, as signing is included in rfm69 radiohead library with mysensors, I don't need atsha? Atsha recommanded with nrf?
-
@scalz
Well, it depends on what you want. In the first post I have outline my stance on the matter. I prefer signing before anything. RF69 offer optional encryption, not signing. If you are happy with just encryption, then you don't need ATSHA but have to use RF69 (or another circuit).
-
@Anticimex : you are right. I confused two different things!! So I think the best is combination of both.
Thank you for your precision and for sharing your work.
-
@scalz
Thanks and you are welcome
-
@scalz
For the record, I share your opinion on using a combination. I will probably go for that myself when I fully deploy my sensornetwork. RF69 with AES encryption on RF level, and ATSHA authentication on protocol level should be enough to protect against most deliberate non-physical mischief.
-
@Anticimex : I totally agree with you. I am still defining my needs too. I have only some nrf nodes but I think Mysensors + RFM + Atsha + ota=Zwave killer! it might eliminate repeater needs.
On my designs I put nrf and rfm footprints but I think I will move to rfm as soon as I can. I will share my designs when it will be tested. Hope there will be lots of boards for mysensors in the future.
Have a good day!
-
@scalz
I have actually designed a board that supports both radios. I have just received them but have not mounted them with components yet so I have not been able to verify the design. But I will post it on the forum as soon as I have. It will be pin-compatible with Sensbender Micro but also support RF69. It is not intended to be replacing that board nor is it an "official" MySensor board. I have just designed it to fit my personal preferences and to serve as a generic multi-purpose sensor backend (it relies on modules and has a lot of headers to support many sensors in parallel on both 3.3 and 5V rails).
-
wow. can't wait to see your creations! Seems interesting. Your board could be very helpful.
I love Sensebender. But 0402, it was difficult to solder for me! So I am trying to use 0805 in my designs, easier for me.
I am finishing to modify a moteino (0805 so a little bigger) to add nrf and atsha. I am waiting for others boards (not received yet) : uCurrent module, one power management optimization board (based on ulpnode idea), esp8266-07 with nrf, rfm and atsha (I will try to make sort of mqtt gateway), and a mysensors relay board. I have others idea too: dimmer for one main, hb100 (for barrier security), mgc3030 (for gesture. lot of stuff on this one I think). But before I must finish what I started. Hihi, mysensors and automation is addictive!I read in previous post that you advised not to use A6,A7 for atsha. But I imagine that I can use others pin (if i take care of datasheet of course)? I think it is doable, just have to modify pin ref in code next, isn't it? Anyway, I always try to keep mysensors reference design (A3), it is just for personal info.
-
@scalz
Then you'll be happy to hear that my board uses 0805 and 1206 and also has enlarged pads for hand soldering on all SMD footprints
It also features a jumper for current measurement, three power connection options, switchable regulators for super low standby currents and some other features. But I will give the details in a separate post.
-
@scalz
Regarding pin, yes. You can freely choose any digital IO for ATSHA. A6 and A7 are not digital IO so they cannot be used. They are pure analog.
-
Very interesting. So your board will be a great addition. I will follow your work for sure!
Thank you very much for your help.
-
Hi @all!
First off all: thanks for your great work
I am about to compile the ethernet gw with software signing, but unfortunately I am getting some compile errors.
Does anyone maybe have a sketch handy and would up it here?Thanks in advance and best regards,
Otto
-
@otto001
Sorry, but that is not possible on Arduino Nano. There is not enough flash available to support both ethernet and software signing. You have to use ATSHA for an ethernet gw.
-
@Anticimex:
Thanks, but I am trying to compile it for an UNO R3?! That should do it. Nevertheless: Using nanos only for nodes should work with sw signing, shouldnt it?
-
@otto001
Yep. It is the ethernet stack that costs the most.
I need you to post the compiler error you get though in order to help you.
-
I used the latest devel-branch from github.
This is the error:
In file included from /home/otto/sketchbook/libraries/MySensors/MyTransportNRF24.h:26:0, from /home/otto/sketchbook/libraries/MySensors/MySensor.h:28, from ms_gw_neu.ino:42: /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:11: error: 'SOFT_SPI_MISO_PIN' was not declared in this scope SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; ^ /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:30: error: 'SOFT_SPI_MOSI_PIN' was not declared in this scope SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; ^ /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:49: error: 'SOFT_SPI_SCK_PIN' was not declared in this scope SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; ^ /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:75: error: template argument 1 is invalid SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; ^ /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:75: error: template argument 2 is invalid /home/otto/sketchbook/libraries/MySensors/utility/RF24.h:51:75: error: template argument 3 is invalid In file included from ms_gw_neu.ino:43:0: /home/otto/sketchbook/libraries/MySensors/MyGateway.h:39:28: error: 'DEFAULT_CE_PIN' was not declared in this scope MyGateway(uint8_t _cepin=DEFAULT_CE_PIN, uint8_t _cspin=DEFAULT_CS_PIN, uint8_t _inclusion_time = 1, uint8_t _inclusion_pin = 3, uint8_t _rx=6, uint8_t _tx=5, uint8_t _er=4); ^ /home/otto/sketchbook/libraries/MySensors/MyGateway.h:39:59: error: 'DEFAULT_CS_PIN' was not declared in this scope MyGateway(uint8_t _cepin=DEFAULT_CE_PIN, uint8_t _cspin=DEFAULT_CS_PIN, uint8_t _inclusion_time = 1, uint8_t _inclusion_pin = 3, uint8_t _rx=6, uint8_t _tx=5, uint8_t _er=4); ^ ms_gw_neu.ino:80:31: error: no matching function for call to 'MyGateway::MyGateway(MyTransportNRF24&, MyHwATMega328&, MySigningAtsha204Soft&)' ms_gw_neu.ino:80:31: note: candidates are: In file included from ms_gw_neu.ino:43:0: /home/otto/sketchbook/libraries/MySensors/MyGateway.h:39:3: note: MyGateway::MyGateway(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t) MyGateway(uint8_t _cepin=DEFAULT_CE_PIN, uint8_t _cspin=DEFAULT_CS_PIN, uint8_t _inclusion_time = 1, uint8_t _inclusion_pin = 3, uint8_t _rx=6, uint8_t _tx=5, uint8_t _er=4); ^ /home/otto/sketchbook/libraries/MySensors/MyGateway.h:39:3: note: no known conversion for argument 1 from 'MyTransportNRF24' to 'uint8_t {aka unsigned char}' /home/otto/sketchbook/libraries/MySensors/MyGateway.h:20:7: note: MyGateway::MyGateway(const MyGateway&) class MyGateway : public MySensor ^ /home/otto/sketchbook/libraries/MySensors/MyGateway.h:20:7: note: candidate expects 1 argument, 3 provided
and this is the sketch - I am not sure, if everything is right (I am not deep into mysensors yet):
/* * Copyright (C) 2013 Henrik Ekblad <henrik.ekblad@gmail.com> * * Contribution by a-lurker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * DESCRIPTION * The EthernetGateway sends data received from sensors to the ethernet link. * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. * * The GW code is designed for Arduino 328p / 16MHz. ATmega168 does not have enough memory to run this program. * * * COMPILING WIZNET (W5100) ETHERNET MODULE * > Edit RF24_config.h in (libraries\MySensors\utility) to enable softspi (remove // before "#define SOFTSPI"). * * COMPILING ENC28J60 ETHERNET MODULE * > Use Arduino IDE 1.5.7 (or later) * > Disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch will probably not fit in program space when downloading. * > Remove Ethernet.h include below and include UIPEthernet.h * > Remove DigitalIO include * Note that I had to disable UDP and DHCP support in uipethernet-conf.h to reduce space. (which means you have to choose a static IP for that module) * * VERA CONFIGURATION: * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003 * * LED purposes: * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly * - ERR (red) - fast blink on error during transmission error or recieve crc error * * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. * */ #include <DigitalIO.h> // This include can be removed when using UIPEthernet module #include <SPI.h> #include <MySensor.h> #include <MyGateway.h> #include <stdarg.h> #include <MyConfig.h> #include <MySigningAtsha204Soft.h> // Use this if you have attached a Ethernet ENC28J60 shields //#include <UIPEthernet.h> // Use this fo WizNET W5100 module and Arduino Ethernet Shield #include <Ethernet.h> #define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled #define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button #define RADIO_CE_PIN 5 // radio chip enable #define RADIO_SPI_SS_PIN 6 // radio SPI serial select #define RADIO_ERROR_LED_PIN 7 // Error led pin #define RADIO_RX_LED_PIN 8 // Receive led pin #define RADIO_TX_LED_PIN 9 // the PCB, on board LED #define IP_PORT 5003 // The port you want to open IPAddress myIp (192, 168, 1, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later! // The MAC address can be anything you want but should be unique on your network. // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. // Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. byte mac[] = { 0xCE, 0x0D, 0xBE, 0xEF, 0xFE, 0xED }; // DEAD BEEF FEED // a R/W server on the port EthernetServer server = EthernetServer(IP_PORT); MyTransportNRF24 radio; // NRFRF24L01 radio driver MyHwATMega328 hw; // Select AtMega328 hardware profile MySigningAtsha204Soft signer(false); // Select ATSHA204A software signing backend MyGateway gw(radio, hw, signer); // No blink or button functionality. Use the vanilla constructor. // old MyGateway gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, INCLUSION_MODE_TIME); // Uncomment this constructor if you have leds and include button attached to your gateway //MyGateway gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, INCLUSION_MODE_TIME, INCLUSION_MODE_PIN, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface int inputPos = 0; void setup() { Ethernet.begin(mac, myIp); // give the Ethernet interface a second to initialize delay(1000); // Initialize gateway at maximum PA level, channel 70 and callback for write operations gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet); // start listening for clients server.begin(); } // This will be called when data should be written to ethernet void writeEthernet(char *writeBuffer) { server.write(writeBuffer); } void loop() { // if an incoming client connects, there will be // bytes available to read via the client object EthernetClient client = server.available(); if (client) { Serial.print("bytes"); // if got 1 or more bytes if (client.available()) { // read the bytes incoming from the client char inChar = client.read(); if (inputPos<MAX_RECEIVE_LENGTH-1) { // if newline then command is complete if (inChar == '\n') { // a command was issued by the client // we will now try to send it to the actuator inputString[inputPos] = 0; // echo the string to the serial port Serial.print(inputString); gw.parseAndSend(inputString); // clear the string: inputPos = 0; } else { // add it to the inputString: inputString[inputPos] = inChar; inputPos++; } } else { // Incoming message too long. Throw away inputPos = 0; } } } gw.processRadioMessage(); }
Thanks for your help in advance!
Otto
-
@otto001
Hm. Looks like you have a problem with your settings for soft SPI. The errors are not related to the signing backend.
I suspect a problem in MyConfig.h but I have not been up to speed with the changes on development nor have I dabbled with soft SPI. I run "hardware" SPI. @hek maybe knows what setting is wrong for your problem to occur. Could be that the soft SPI driver does not take UNO boards into account?
-
Thanks anyway! I will try again without signing. Maybe there is a problem in the recent devel-branch. With stable 1.4 it compiled without any issues...
/update: does not compile with the "standard" ethernet-gw sketch too.... not related to signing...
-
@otto001
Alright. Thanks for confirming. I had a rough period on development with the signing support when I was developing it. Other commits kept breaking it (not intentionally but because there was other changes to the init sequences and such which did not take signing into account). And I have been busy doing other things so I have not refreshed my own sketches to HEAD on development for a couple of months so I am uncertain on the working state at the moment, but I trust @hek to let me know if something breaks again
I will get back on track soon I hope but project is coming up and is sure to mess quite a bit with my schedule so I trust others to keep me informed if signing support should fail.
-
I do not understand how to set the Backend in the myconfig.h.
"you need to decide what signing backend to use. This is done in MyConfig.h"
But how? Just by commenting out the Pin Define?
-
My post is not really up2date with the code at the moment (at least on development branch). You now pick you backend by argument to the MySensor constructor. I will check with @hek how we should handle this post when master and development are diverging.
-
Thank you for your quick reply Now it is clearer to me.
-
Good! I will look into how the post can be clearer and handle the code specifics better with respect to both "master" and "development" where applicable. Sorry for the discrepancy
-
First post updated to better reflect the state of the 'development' branch. Signing is currently not available on 'master'.
-
Hi @Anticimex,
I read your first post and followed it, it was very interesting and comprehensible. So I am trying autentication to see how it looks. I entered the key in a Gateway (nano) and a mini pro node. The mini is running DHT Humidity sketch (I know it is not very interesting node for autentication but it's easy on breadboard). I am using latest dev branch. Communication seems to work but i am a little confused with serial output on GW as I see some no sign. It seems that humidity is ok, but not the temperature child.. but I am not sure.
What do you think I am doing wrong?
Edit: I am getting others nosign... Does presentation and version messages uses autentication too? because they seem to be ok but not the child sensors value..
Here is GW logs:
0;0;3;0;9;read: 10-10-0 s=255,c=3,t=15,pt=2,l=2,sg=0:1 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=15,pt=2,l=2,sg=0,st=ok:1 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01F989B 0;0;3;0;9;read: 10-10-0 s=255,c=0,t=17,pt=0,l=6,sg=1:1.5 b1 10;255;0;0;17;1.5 b1 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:017DA4B 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=6,pt=1,l=1,sg=1:0 10;255;3;0;6;0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01C7E11 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=11,pt=0,l=8,sg=1:Humidity 10;255;3;0;11;Humidity 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:017B669 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=12,pt=0,l=3,sg=1:1.0 10;255;3;0;12;1.0 0;0;3;0;9;read: 10-10-0 s=0,c=0,t=7,pt=0,l=0,sg=0: 10;0;0;0;7; 0;0;3;0;9;read: 10-10-0 s=1,c=0,t=6,pt=0,l=0,sg=0: 10;1;0;0;6; 0;0;3;0;9;no sign 0;0;3;0;9;no sign
-
@scalz Thanks.
Could you please also post the construction code of your MySensor object.
And also your MyConfig.h changes (where you enable the signing functionality). Don't post your private key though
The initial setup is all signed and well but then your node seem to not even attempt to sign the data it sends (because it should have sent a c=3,t=16 and waited for a c=3,t=17 prior to any sensor data).
I see from the first two messages that the gateway has been informed that your sensor require signatures (of messages from the gateway). And the gateway do respond that it also require signautres but for some reason your sensor do not sign the sensor values (the presentation handshaking is transmitted in signed form as expected).
I don't have a quick answer to why your node does not sign it's sensor data. Could you also share your code that transmits (in your sketch that is). Perhaps the easiest is to post the entire sketch (WITHOUT your private key).I am afraid I have to prioritize my newborn son, so I hope for understanding if my replies will be delayed. @hek might know if something has happened on dev branch that could affect signing. I did thoroughly test it when it was submitted but I have not been keeping track on activities on dev for a while now.
-
@Anticimex: Congratulation for your son! it is not hurry, no problem. and thank you for taking time.
So maybe I am missing something, because I have no key in the sketch??? I am using ATSHA hardware chip.. The key is stored by using SHAPersonalizer, isn't it??I have not made any changes in Myconfig.h as it is default enabled. So it is like this:
// Disable to completly disable signing functionality in library #define MY_SIGNING_FEATURE
And the node sketch:
#include <SPI.h> #include <MyTransportNRF24.h> #include <MyHwATMega328.h> #include <MySensor.h> #include <DHT.h> #include <MySigningAtsha204.h> #define CHILD_ID_HUM 0 #define CHILD_ID_TEMP 1 #define HUMIDITY_SENSOR_DIGITAL_PIN 5 unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) MyTransportNRF24 radio; // NRFRF24L01 radio driver MyHwATMega328 hw; // Select AtMega328 hardware profile MySigningAtsha204 signer; // Select HW ATSHA signing backend MySensor gw(radio, hw, signer); DHT dht; float lastTemp; float lastHum; boolean metric = true; MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); void setup() { gw.begin(NULL, 10); dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // Send the Sketch Version Information to the Gateway gw.sendSketchInfo("Humidity", "1.0"); // Register all sensors to gw (they will be created as child devices) gw.present(CHILD_ID_HUM, S_HUM); gw.present(CHILD_ID_TEMP, S_TEMP); metric = gw.getConfig().isMetric; } void loop() { delay(dht.getMinimumSamplingPeriod()); float temperature = dht.getTemperature(); if (isnan(temperature)) { Serial.println("Failed reading temperature from DHT"); } else if (temperature != lastTemp) { lastTemp = temperature; if (!metric) { temperature = dht.toFahrenheit(temperature); } gw.send(msgTemp.set(temperature, 1)); Serial.print("T: "); Serial.println(temperature); } float humidity = dht.getHumidity(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum) { lastHum = humidity; gw.send(msgHum.set(humidity, 1)); Serial.print("H: "); Serial.println(humidity); } gw.sleep(SLEEP_TIME); //sleep a bit }
and in Serial Gateway, I have only changed this:
// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) //MySigningNone signer; //MySigningAtsha204Soft signer; MySigningAtsha204 signer; // Hardware profile MyHwATMega328 hw; // Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) // To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h #ifdef WITH_LEDS_BLINKING MySensor gw(transport, hw , signer, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); #else MySensor gw(transport, hw , signer); #endif
-
@scalz Thanks
Correct. With HW ATSHA204A no key in the sketch is necessary.
And your setup seem ok since there are signed messages being passed successfully so the HW seem ok.Perhaps you could add a debug print that dumps your messages in the gateway before they are checked for signatures in MySensor::process?
Just putdebug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d\n"), msg.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, mGetPayloadType(msg), mGetLength(msg), mGetSigned(msg));
before#ifdef MY_SIGNING_FEATURE
.
You could also do the corresponding thing in your nodes MySensor::sendRoute function so we can see what data you send in order to determine why your node has decided it should not be signed.It could be you stumbled over a library bug because I see in the code that in sendRoute the if case looks funky.
It says:
if (DO_SIGN(message.destination) && message.sender == nc.nodeId && !mGetAck(message) && mGetLength(msg) &&
but I think it should say
if (DO_SIGN(message.destination) && message.sender == nc.nodeId && !mGetAck(message) && mGetLength(message) &&
Try to change this and see what happens. I have a strong suspicion that your node's msg buffer is empty, and sendRoute therefore don't sign the message because it gets the length from the wrong buffer.@hek if @scalz tests this successfully, could you patch it? I think it is a bug that it checks
mGetLength(msg)
and notmGetLength(message)
in MySensor::sendRoute.
-
@Anticimex
I could probably fix it tonight if it turns out wrong.
-
@Anticimex @Hek
Thank you very much for debugging!
First, I tried to add the debug watch. And like you said it seems there was no value.
Then, I looked at sendRoute like you advised, and oh!, it makes sense. A tiny small bug is living there !
So I changed mGetLength(msg) with mGetLength(message)
And now... it seems to work well! yeah! I am so happyIf you want below is my GW logs (with the debug watch too), but I think it's ok now. there is no unwanted "nosign" anymore.
0;0;3;0;9;gateway started, id=0, parent=0, distance=0 0;0;3;0;14;Gateway startup complete. 0;0;3;0;9;read: 0-0-0 s=0,c=0,t=0,pt=0,l=0,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=15,pt=2,l=2,sg=0:1 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=15,pt=2,l=2,sg=0,st=ok:1 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=15,pt=2,l=2,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01F428B 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=0,t=17,pt=0,l=6,sg=1:1.5 b1 10;255;0;0;17;1.5 b1 0;0;3;0;9;read: 10-10-0 s=255,c=0,t=17,pt=0,l=6,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:013E014 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=6,pt=1,l=1,sg=1:0 10;255;3;0;6;0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=6,pt=1,l=1,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:0174D82 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=11,pt=0,l=8,sg=1:Humidity 10;255;3;0;11;Humidity 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=11,pt=0,l=8,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01827E7 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=12,pt=0,l=3,sg=1:1.0 10;255;3;0;12;1.0 0;0;3;0;9;read: 10-10-0 s=255,c=3,t=12,pt=0,l=3,sg=0 0;0;3;0;9;read: 10-10-0 s=0,c=0,t=7,pt=0,l=0,sg=0: 10;0;0;0;7; 0;0;3;0;9;read: 10-10-0 s=0,c=0,t=7,pt=0,l=0,sg=0 0;0;3;0;9;read: 10-10-0 s=1,c=0,t=6,pt=0,l=0,sg=0: 10;1;0;0;6; 0;0;3;0;9;read: 10-10-0 s=1,c=0,t=6,pt=0,l=0,sg=0 0;0;3;0;9;read: 10-10-0 s=1,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01E4D70 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=1,c=1,t=0,pt=7,l=5,sg=1:23.0 10;1;1;0;0;23.0 0;0;3;0;9;read: 10-10-0 s=1,c=1,t=0,pt=7,l=5,sg=0 0;0;3;0;9;read: 10-10-0 s=0,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-10-10 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:0148CE9 0;0;3;0;9;read: 0-0-10 s=255,c=3,t=17,pt=6,l=25,sg=0 0;0;3;0;9;read: 10-10-0 s=0,c=1,t=1,pt=7,l=5,sg=1:36.0 10;0;1;0;1;36.0
I have just a last question regarding signature :
- in the future, when Mysensors new version will be released, does the controller will have to check the signature and to store the PSK? I think so, as the logs shows it is crypted. For doing this we should inspire ourselves
with your atsha_soft, isn't it? It is just curiosity of mine, as I am looking at your libs, and I am thinking about what changes will be involved on controller side when the moment will come for plugin update...
Now, I have to check the atsha soft version too, then ota with the recently great improvement of tekka..., and understand all new changes in the message format...lots of things.
I like this lib! 1.4 is smart, but dev branch looks very well done and much more optimized.See you soon!
- in the future, when Mysensors new version will be released, does the controller will have to check the signature and to store the PSK? I think so, as the logs shows it is crypted. For doing this we should inspire ourselves
-
@scalz Great! Thanks for finding and testing this.
I am not sure I understand your question. You mean to store the PSK of atsha_soft in encrypted form in the sketch? That is difficult since the encryption secret then needs to be stored somewhere as well.
I would recommend (if you do use atsha_soft) to burn the fuses to prevent memory readout to protect the PSK.
Normally, this implementation is stored in the gateway which should be physically protected in any case, so the need to protekt PSK in the gateway is less critical than in a node which may be located "outside".Secure OTA is currently unsupported. It might be supported in the future.
-
Oh, sorry for my bad english!
Is signing just between a Node and a Gateway. or is the controller involved too? Maybe it's a dumb question, I have not checked yet the changes in message.
For OTA, I understand it is not suppported by signature as you explained in your tuto. But, in the other hand, I think that for initiating an ota, it should need a signed message, so I think it is good.
-
@scalz You decide if your component will require signatures when you create your signer. That is, if you want your gateway to be able to sign messages sent to an actuator (like a lock) but you don't want your gateway to require signed messages from your nodes, you pass a argument to the constructor like this:
MySigningAtsha204 signer(false);
That will- Configure that node/gw to support signed message processing using HW ATSHA
- Have that node/gw inform others that it does not require signed messages
- Still permit that node/gw to sign messages sent to other nodes/gw who do requre signing
If you stick to default constructor arguments or pass
true
, the difference is that the node/gw will also inform others that it requires signed messages, and will ignore/discard any message that is not signed which it receive (and is targeted to that particular node/gw). It will not affect messages which are to be relayed, so the node will still work as a relay for unsigned messages.
-
@Anticimex:
ok, it is good to know. You have thought about everything!
If signer(true) for gateway, Will the controller (Jeedom, Domoticz..) see a crypted payload in serial transmission or will it work like before (I understand there are some changes in message structure, but what about crypted payload, does the controller need to decrypt?)
-
@scalz We only sign messages. There is no encryption involved. And the signature is stored without affecting the message contents so it is perfectly compatible with all controllers. The only thing that could affect a controller is the new sign bit in the message header but I don't think that will make any difference as it is not relevant to the controller. It is the gateway that manages this for it.
-
ok, it is new for me, so I am mixing vocabulary, but I understand the concept. Thank you, and now I have my answer. no big changes for controller side, great! It makes sense, but I was not sure.
-
Fix pushed to development.
-
Thanks for that!
-
I put together a garage door opening using code from korttoma. I used soft signing, and it works great. I was wanting to use a real atsha though.
I bought some atsha204a chips from amazon, and the chips are marked with only "3eas", and a "Y" in one corners. They are soic-8. Is that how this should be marked? I wired one up according to the data sheet. Gnd to Gnd, VCC to 5V, and SDA to A3. I ran the personalizer to generate a key and it said "Failed to wake device." in the serial console. Am I doing something wrong? or did I just get the wrong chip from the seller?
-
@jsondag I don't have a good explanation on the software signing not working. Maybe inadequate decoupling leads to a too noisy power rail?
About the HW issue, it is important that you use the single wire version of atsha204. NOT the i2c version. The i2c version also has an scl line while the single wire only has sda (and power and ground). That means your soic8 should have 5 unused pads. Atmel ordering code for that variant is ATSHA204A-SSHCZ-T but unfortunately it is not printed on the case. So unless you find that information from Amazon, I am afraid it is very difficult to determine the type of the chips you've got.
-
@Anticimex. Software signing is working fine.
Thanks for the information though. I didn't realize the soic 8 couldn't do one wire. It's a ATSHA204-SH-DA-B according to the listing.
EDIT:
Looking at the datasheet, it says that the SCL pin can be ignored for single wire interface. perhaps I'll wire another one up and give it a go.Just connect, SDA to A3, correct?
-
@jsondag ok. From what I could read there are two different order codes for i2c and one-wire so I don't think you can take an i2c variant board and treat it as a one-wire board by just ignoring the scl pin. But if the board really is single-wire, the pinout will be the same as the i2c version, you can just ignore the scl pin as it is NC for the one-wire variant. And from the data sheet, SHDAB is i2c not "single-wire" so I am afraid you cannot use my libs for those. I only have drivers for single-wire chips i am afraid.
-
I just received my chips today from digikey (part num ATSHA204A-STUCZ-TCT-ND) which are the small 3 pin versions. Holy cow these are things are tiny. These are going to be a lot more difficult than I expected to hand solder.
-
@TD22057 If you don't have a "inverse" tweezer to fixate the chip to the board, just glue it in place. With proper iron temp (at least 300 deg C, I use 330) it's very doable. Much easier than smd resistors/caps if you ask me (just don't forget to solder after you glue if you do that)
-
@Anticimex said:
@TD22057 If you don't have a "inverse" tweezer to fixate the chip to the board, just glue it in place. With proper iron temp (at least 300 deg C, I use 330) it's very doable. Much easier than smd resistors/caps if you ask me (just don't forget to solder after you glue if you do that)
Thanks - I'll try that as soon as everything arrives. Watching parts trickle in from aliexpress shippers is killing me (I think I've become spoiled on Amazon prime shipping).
-
First of all I would like to thank Anticimex for this great piece of work!
I am playing around with signing right now. I set up a temp & humid sensor with soft signing support as well as a MQTT gateway with soft signing.
In principle it seems to work. At least sensor values are published to the MQTT broker. However, in the gateway output I see nonce tr errors and sign failures.
Started! 0;0;3;0;9;read: 21-21-0 s=1,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:0107FD8 0;0;3;0;9;read: 21-21-0 s=1,c=1,t=0,pt=7,l=5,sg=1:25.1 publish: MyMQTT/21/1/V_TEMP 25.1 0;0;3;0;9;read: 21-21-0 s=2,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:012B06D 0;0;3;0;9;send: 0-0-21-21 s=1,c=3,t=16,pt=0,l=0,sg=0,st=ok: 0;0;3;0;9;read: 21-21-0 s=2,c=1,t=1,pt=7,l=5,sg=1:59.0 publish: MyMQTT/21/2/V_HUM 59.0 0;0;3;0;9;sign fail 0;0;3;0;9;send: 0-0-21-21 s=2,c=3,t=16,pt=0,l=0,sg=0,st=fail: 0;0;3;0;9;nonce tr err 0;0;3;0;9;read: 21-21-0 s=255,c=3,t=17,pt=6,l=25,sg=0:01D5F523C2778AA 0;0;3;0;9;read: 21-21-0 s=1,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:0104881 0;0;3;0;9;read: 21-21-0 s=1,c=1,t=0,pt=7,l=5,sg=1:25.1 publish: MyMQTT/21/1/V_TEMP 25.1 0;0;3;0;9;read: 21-21-0 s=2,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:019A79B 0;0;3;0;9;send: 0-0-21-21 s=1,c=3,t=16,pt=0,l=0,sg=0,st=ok: 0;0;3;0;9;read: 21-21-0 s=2,c=1,t=1,pt=7,l=5,sg=1:59.2 publish: MyMQTT/21/2/V_HUM 59.2 0;0;3;0;9;sign fail 0;0;3;0;9;send: 0-0-21-21 s=2,c=3,t=16,pt=0,l=0,sg=0,st=fail: 0;0;3;0;9;nonce tr err 0;0;3;0;9;read: 21-21-0 s=255,c=3,t=17,pt=6,l=25,sg=0:0120D83204D1A06 0;0;3;0;9;read: 21-21-0 s=1,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01AB761 0;0;3;0;9;read: 21-21-0 s=1,c=1,t=0,pt=7,l=5,sg=1:25.1 publish: MyMQTT/21/1/V_TEMP 25.1 0;0;3;0;9;read: 21-21-0 s=2,c=3,t=16,pt=0,l=0,sg=0: 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:013CD41 0;0;3;0;9;read: 21-21-0 s=2,c=1,t=1,pt=7,l=5,sg=1:59.3 publish: MyMQTT/21/2/V_HUM 59.3 0;0;3;0;9;send: 0-0-21-21 s=1,c=3,t=16,pt=0,l=0,sg=0,st=fail: 0;0;3;0;9;nonce tr err 0;0;3;0;9;send: 0-0-21-21 s=2,c=3,t=16,pt=0,l=0,sg=0,st=fail: 0;0;3;0;9;nonce tr err
I am somehow irritated concerning those failures logged after the publish logs. They seem not to be related to receiving and publishing the sensor data. What can be source of that? Why might the gateway trying to transmit?
A second question is related to personalization of the ATSHA204. Am I right that the key is displayed in the SlotConfig00 - SlotConfig0F?
The second personalization step fails with the message "Data lock failed". What could be the reason for that?
-
@tomkxy Thanks.
"nonce tr err" is sent if sendRoute() fails to send a nonce request. So it suggests the radio link is somewhat unreliable and that in turn causes signing to fail. From what I can see you want to sign messages in both directions, so maybe traimsission from the MQTT gateway is not as reliable as reception? message type 16 (command 3) is a nonce request and sometimes it succeeds0;0;3;0;9;send: 0-0-21-21 s=1,c=3,t=16,pt=0,l=0,sg=0,st=ok:
and sometimes it fail (with that message as consequence):
0;0;3;0;9;send: 0-0-21-21 s=2,c=3,t=16,pt=0,l=0,sg=0,st=fail: 0;0;3;0;9;nonce tr err
But the failing one is to a different sensor (2) than the first one (1), so perhaps that node is down or at a long range? But last in your log you also fail a transmission to sensor 1. In any case, the nonce tr err is because of failing radio transmissions and as such not a signing issue as such. Sometimes it works (when there are no radio issues:
0;0;3;0;9;read: 21-21-0 s=1,c=3,t=16,pt=0,l=0,sg=0: (request for nonce to GW) 0;0;3;0;9;send: 0-0-21-21 s=255,c=3,t=17,pt=6,l=25,sg=0,st=ok:01AB761 (GW sends nonce back) 0;0;3;0;9;read: 21-21-0 s=1,c=1,t=0,pt=7,l=5,sg=1:25.1 (signed message with that nonce is received) publish: MyMQTT/21/1/V_TEMP 25.1 (message/signature is accepted and forwarded)
"sign fail" is typically reported if nonce exchange times out. You can adjust the timeout using MY_VERIFICATION_TIMEOUT_MS if you have many hops or for other reasons cannot process messages fast enough.
I have not tested MQTT gateway myself, and perhaps it uses the MySensors library differently but I have tested both serial and ethernet gateway. But in this case, it probably fails because you never got the request for the nonce out so your sender never got a chance to send a nonce back, and therefore signing cannot succeed.
So the key is to determine why the transmission of the nonce request fail (a radio problem since you get st=fail). Or implement a retransmission at a higher level in your sketch if the radio link is "lossy". The signing backend assumes a working channel and do not handle retransmission for you on failures.Regarding personalization, key is never displayed. It is stored in slot 0. Slotconfigs are used to set the permissions of the slots. They don't store keys themselves.
You should get the reason for the data lock failure in the code that is sent together with the message. It is the ATSHA circuit itself that provide this value (or the library communicating with it in case of communication problem).
-
Thanks for your fast reply. Regarding the communication failures: I was testing this with both transmitters lying side by side. Do you have any idea why the gateway might want to have a nonce. Is it part of the sensor protocol?
The two sensors displayed in the log are basically the same sensor (DHT22 providing temp and humidity).With respect to the key topic: The first personalization step provides the following output:
Device revision: 00020009 Device serial: {0x01,0x23,0x48,0xC9,0x51,0x6A,0x1A,0x06,0xEE} 012348C9516A1A06EE Chip configuration: SN[0:1] | SN[2:3] | 01 23 | 48 C9 Revnum | 00 09 04 00 SN[4:7] | 51 6A 1A 06 SN[8] | Reserved13 | I2CEnable | Reserved15 | EE | 13 | 00 | 00 I2CAddress | TempOffset | OTPmode | SelectorMode | C8 | 00 | 55 | 00 SlotConfig00 | SlotConfig01 | 8F 80 | 80 A1 SlotConfig02 | SlotConfig03 | 82 E0 | A3 60 SlotConfig04 | SlotConfig05 | 94 40 | A0 85 SlotConfig06 | SlotConfig07 | 86 40 | 87 07 SlotConfig08 | SlotConfig09 | 0F 00 | 89 F2 SlotConfig0A | SlotConfig0B | 8A 7A | 0B 8B SlotConfig0C | SlotConfig0D | 0C 4C | DD 4D SlotConfig0E | SlotConfig0F | C2 42 | AF 8F UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | FF | 00 | FF | 00 UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | FF | 00 | FF | 00 UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | FF | 00 | FF | 00 UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | FF | 00 | FF | 00 LastKeyUse[0:3] | FF FF FF FF LastKeyUse[4:7] | FF FF FF FF LastKeyUse[8:B] | FF FF FF FF LastKeyUse[C:F] | FF FF FF FF UserExtra | Selector | LockValue | LockConfig | 00 | 00 | 55 | 55
Can I provide any key in the second personalization step or does it have to be same than in the first step being generated?
-
@tomkxy The protocol is described in the first post. Any node that is sending a signed message to another node (that has requested to get signed messages) will ask for a nonce. So you have configured your gateway to require signed messages as well as your node.
Regarding the personalization, I do t understand your question. The output is the chip configuration. It does not list any keys. I am not sure I understand what you mean by second step. You can generate a random key and that key you store and after you store it you have an option to also lock it, but then you have no way of ever changing it. I have documented the personalization flow also in the sketch itself.
-
I should emphasise that if you personalize multiple atsha:s you have to have the same key stored in all of them. But the sketch offer to generate a random key (but you can skip that and use any key or password you like). But the key must be the same for all members of a secure network that want to talk to each other.
-
@Anticimex: The output shown is related to the sketch configuration you described in your description:
Set the following sketch configuration of the personalizer:
Enable LOCK_CONFIGURATION
Disable LOCK_DATA
Enable SKIP_KEY_STORAGE
Disable SKIP_UART_CONFIGURATION
Disable USER_KEY_DATAExecute the sketch on the “master” device to obtain a randomized key. Save this key to >a secure location and keep it confidential so that you can retrieve it if you need to
personalize more devices later on.I was wondering that I did not see any explicit reference to a key. So may be I just have to retry.
I should emphasise that if you personalize multiple atsha:s you have to have the same >key stored in all of them. But the sketch offer to generate a random key (but you can >skip that and use any key or password you like). But the key must be the same for all >members of a secure network that want to talk to each other.
Thanks for that clarification. I was aware of that.
-
@tomkxy are you sure you have enabled all those options? According to the dump, your configuration is still not locked and therefore no randomized key can be generated. Are there no more output from the sketch than that? You mentioned failure to lock data zone but I cannot see that message. And you cannot lock datazone without locking configuration.
After the sketch locks configuration it will print a randomized key in the log.
-
@Anticimex: Thanks for your patience and your support.
I rerun it with the output and sketch configuration listed below. May be the reason that it is not working that my poor soldering skills bricked the device.Extract from sketch (1st run):
#include <sha204_library.h> #include <sha204_lib_return_codes.h> // The pin the ATSHA204 is connected on #define ATSHA204_PIN 17 // A3 // Uncomment this to enable locking the configuration zone. // *** BE AWARE THAT THIS PREVENTS ANY FUTURE CONFIGURATION CHANGE TO THE CHIP *** // It is still possible to change the key, and this also enable random key generation #define LOCK_CONFIGURATION // Uncomment this to enable locking the data zone. // *** BE AWARE THAT THIS PREVENTS THE KEY TO BE CHANGED *** // It is not required to lock data, key cannot be retrieved anyway, but by locking // data, it can be guaranteed that nobody even with physical access to the chip, // will be able to change the key. //#define LOCK_DATA // Uncomment this to skip key storage (typically once key has been written once) #define SKIP_KEY_STORAGE // Uncomment this to skip key data storage (once configuration is locked, key // will aways randomize) // Uncomment this to skip key generation and use 'user_key_data' as key instead. //#define USER_KEY_DATA // Uncomment this for boards that lack UART // IMPORTANT: No confirmation will be required for locking any zones with this // configuration! // Also, key generation is not permitted in this mode as there is no way of // presenting the generated key. //#define SKIP_UART_CONFIRMATION #if defined(SKIP_UART_CONFIRMATION) && !defined(USER_KEY_DATA) #error You have to define USER_KEY_DATA for boards that does not have UART #endif …
Output:
ATSHA204 personalization sketch for MySensors usage. ---------------------------------------------------- Device revision: 00020009 Device serial: {0x01,0x23,0x48,0xC9,0x51,0x6A,0x1A,0x06,0xEE} 012348C9516A1A06EE Skipping configuration write and lock (configuration already locked). Chip configuration: SN[0:1] | SN[2:3] | 01 23 | 48 C9 Revnum | 00 09 04 00 SN[4:7] | 51 6A 1A 06 SN[8] | Reserved13 | I2CEnable | Reserved15 | EE | 13 | 00 | 00 I2CAddress | TempOffset | OTPmode | SelectorMode | C8 | 00 | 55 | 00 SlotConfig00 | SlotConfig01 | 8F 80 | 80 A1 SlotConfig02 | SlotConfig03 | 82 E0 | A3 60 SlotConfig04 | SlotConfig05 | 94 40 | A0 85 SlotConfig06 | SlotConfig07 | 86 40 | 87 07 SlotConfig08 | SlotConfig09 | 0F 00 | 89 F2 SlotConfig0A | SlotConfig0B | 8A 7A | 0B 8B SlotConfig0C | SlotConfig0D | 0C 4C | DD 4D SlotConfig0E | SlotConfig0F | C2 42 | AF 8F UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | FF | 00 | FF | 00 UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | FF | 00 | FF | 00 UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | FF | 00 | FF | 00 UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | FF | 00 | FF | 00 LastKeyUse[0:3] | FF FF FF FF LastKeyUse[4:7] | FF FF FF FF LastKeyUse[8:B] | FF FF FF FF LastKeyUse[C:F] | FF FF FF FF UserExtra | Selector | LockValue | LockConfig | 00 | 00 | 55 | 00 Disable SKIP_KEY_STORAGE to store key. Data not locked. Define LOCK_DATA to lock for real. -------------------------------- Personalization is now complete. Configuration is LOCKED Data is UNLOCKED
Second run with the following sketch settings (key used removed):
#include <sha204_library.h> #include <sha204_lib_return_codes.h> // The pin the ATSHA204 is connected on #define ATSHA204_PIN 17 // A3 // Uncomment this to enable locking the configuration zone. // *** BE AWARE THAT THIS PREVENTS ANY FUTURE CONFIGURATION CHANGE TO THE CHIP *** // It is still possible to change the key, and this also enable random key generation #define LOCK_CONFIGURATION // Uncomment this to enable locking the data zone. // *** BE AWARE THAT THIS PREVENTS THE KEY TO BE CHANGED *** // It is not required to lock data, key cannot be retrieved anyway, but by locking // data, it can be guaranteed that nobody even with physical access to the chip, // will be able to change the key. #define LOCK_DATA // Uncomment this to skip key storage (typically once key has been written once) //#define SKIP_KEY_STORAGE // Uncomment this to skip key data storage (once configuration is locked, key // will aways randomize) // Uncomment this to skip key generation and use 'user_key_data' as key instead. #define USER_KEY_DATA // Uncomment this for boards that lack UART // IMPORTANT: No confirmation will be required for locking any zones with this // configuration! // Also, key generation is not permitted in this mode as there is no way of // presenting the generated key. #define SKIP_UART_CONFIRMATION #if defined(SKIP_UART_CONFIRMATION) && !defined(USER_KEY_DATA) #error You have to define USER_KEY_DATA for boards that does not have UART #endif #ifdef USER_KEY_DATA #define MY_HMAC_KEY 0x… const uint8_t user_key_data[32] = {MY_HMAC_KEY}; #endif const int sha204Pin = ATSHA204_PIN; atsha204Class sha204(sha204Pin);
Device revision: 00020009 Device serial: {0x01,0x23,0x48,0xC9,0x51,0x6A,0x1A,0x06,0xEE} 012348C9516A1A06EE Skipping configuration write and lock (configuration already locked). Chip configuration: SN[0:1] | SN[2:3] | 01 23 | 48 C9 Revnum | 00 09 04 00 SN[4:7] | 51 6A 1A 06 SN[8] | Reserved13 | I2CEnable | Reserved15 | EE | 13 | 00 | 00 I2CAddress | TempOffset | OTPmode | SelectorMode | C8 | 00 | 55 | 00 SlotConfig00 | SlotConfig01 | 8F 80 | 80 A1 SlotConfig02 | SlotConfig03 | 82 E0 | A3 60 SlotConfig04 | SlotConfig05 | 94 40 | A0 85 SlotConfig06 | SlotConfig07 | 86 40 | 87 07 SlotConfig08 | SlotConfig09 | 0F 00 | 89 F2 SlotConfig0A | SlotConfig0B | 8A 7A | 0B 8B SlotConfig0C | SlotConfig0D | 0C 4C | DD 4D SlotConfig0E | SlotConfig0F | C2 42 | AF 8F UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | FF | 00 | FF | 00 UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | FF | 00 | FF | 00 UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | FF | 00 | FF | 00 UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | FF | 00 | FF | 00 LastKeyUse[0:3] | FF FF FF FF LastKeyUse[4:7] | FF FF FF FF LastKeyUse[8:B] | FF FF FF FF LastKeyUse[C:F] | FF FF FF FF UserExtra | Selector | LockValue | LockConfig | 00 | 00 | 55 | 00 Using this user supplied key: #define MY_HMAC_KEY 0x….. Writing key to slot 0... Data lock failed. Response: D3 Halting!
-
@tomkxy I'm on phone so I cannot check the response code right now but you could look it up in the atsha datasheet or in the software. I have not tried to lock data myself and I do not recommend it because it makes it impossible to change the key later on if it is comprised. From what I can see, everything looks good except the locking of the datazone (your key)
-
@tomkxy I should add that from the logs I see that you do have successfully stored your key, so unless you really want to lock down the key, personalization is done and successful.
-
@Anticimex: Thanks a lot. I didn't intend to lock the data zone.
Btw, I did some tests regarding the nonce failure the gateway showed. I think the reason is rather simple. The gateway tried - for reasons I still don't understand - send data to the sensor for which it tried to get a nonce. The sensor however was powered down which is probably the reason why no nonce was sent. At least this error didn't show up when I removed the power down and replaced it by a simple call to delay.
-
@tomkxy Ah, I see. Well then that matter should be sorted.
Regarding your radio issue, yes, if the GW wants to send data to your node, it needs to be up&running. From the log you sent, I cannot determine what data the GW tried to send though, since it (because your node has told the GW it require it) wants to sign the message to send, and fails, the actual message is never showed in the log.
Perhaps you could send a log with your node continuously powered and we could see at least the type of message your GW tries to send. That could help to identify why it tries to send the message in the first place.
-
@Anticimex: I started a new thread http://forum.mysensors.org/topic/1782/gateway-is-sending-command-1-type-1-c-1-t-1-message-to-sensor
because it looks like it is not really related to signing.
In the post I included the log output of the message for which the nonce is being requested. It looks like the gateway node is sending back the humidity with a c=1 command. Somehow this does not make sense to me.
-
@tomkxy I see. Perhaps you request ACK or something like that. But ACKs are not signed. I have seen to that, so probably not. I am not too well into the non-signing aspects of the network though, so hopefully someone else perhaps can give a hint on what's wrong. Could be the sketch itself. I am glad we sorted the signing issues anyway
-
@Anticimex: I found the issue with respect to the gateway sending a message back to the sensor. This is due to the gateway subscribing to all topics on the MQTT broker. Once it receives a message it sends it to the sensor as SET message. I have to resolve that one.
I think, I still have an issue with signing which I need to get sorted myself first. I will let you know.
-
@tomkxy Alright. Good to know that you found the root cause for the message issue.
Regarding signing, from what I could see at least some signed messages did come through, so you should at least have the proper shared states (keys) and configs.
-
I did a few test with my ATSHA204. I could get it working on an Uno. The I took the chip and placed it on my breadboard with my ProMini. I tried to run the SHA Personaliser Sketch again just to make sure that the chip is somehow working and I received an error message that the device cannot be woken up.
Since it worked on the Uno (including running the SHA Personalizer) it must be related to the ProMini (3.3V / 8 MHz).
To what pin do I have to connect the data line?
-
@tomkxy That sounds strange. I have run on ProMini 3.3V/8MHz without issues.
Default is to use A3 for the ATSHA204A. It does not really matter which pin you connect it as long as it is usable for digital I/O (and update MY_ATSHA204_PIN accordingly or provide your pin to the MySigningAtsha204 constructor).
-
How do I change the pin definition if I use A3 on the ProMini?
-
A3 is default setting. You can find the definition of MY_ATSHA204_PIN in MyConfig.h.
-
Yep, it is
`#define MY_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached `` I am just irritate by the 17. So this does map to A3 even on ProMini?
-
@tomkxy yes it does.
-
@Anticimex Unfortunately, I am now in a total state of mess. It seems that nothing works anymore the moment I turn on any signing. For sure, I have a problem with ATSHA204 and the ProMini which I need to sort out separately. I tried them all with my Uno (reading out the config) which worked. When I try to just read the config with my ProMini I get the error cannot wake up device.
But now, even soft signing did not work any longer (it worked first, than I made changes and afte. I just receive nonce transmission errors from the sensor to the gateway although both radios are side by side and transmission without signing works perfectly.
Btw, what is stored in the EPROM and under what circumstances do I have to clear EPROM first. I changed between the various signing feature (soft signing, HW signing, signing required etc.) back and forth and it seems that this info is stored in EPROM and somehow not cleared?? How does the sensor know that the gateway requires signing? Will it get the info out of EPROM? Will this information be updated during presentation?
I think you did a great job on that implementation, the more frustrating it is that I cannot get it to work reliably. I am out for today. May be I find some time tomorrow getting anot ProMini prepared to checkout the issue with the chips.
-
@tomkxy The information stored in EEPROM is not specific to any backend. It just informs the node what other nodes require signed messages. At startup, a node broadcasts it's preference to the gateway which then updates it's EEPROM table and replies with its own preference back so the node knows if the gateway wants signed messages as well. If the preferences differ from what is stored in EEPROM already, it is the updated preferences that will replace the stored preferences.
The usecases for this is if you were to deploy a new sensor which require signing, it would inform gateway of this at startup. But if you restart your gateway it would loose this unless it was stored in EEPROM (the same goes the other way around) so the EEPROM is used so that the signing rules in the network gets preserved even if nodes dissappear or restart.
If you suspect the EEPROM to contain corrupt data, you can clear it with the cleareeorom sketch/example.
The typical circumstance you need to clear EEPROM under is when you switch library version, and the reserved region of EEPROM in the library change (and you also use EEPROM in your sketch). Then the library might take some of your sketch data for "it's own" and that can/will lead to unpredictable results.
-
Just to say, that I tried some weeks ago ATSHA204A with pro mini and had no problem too. Maybe you should try clear eeprom and retry. Or try with another pro mini. But it should work I think.
And for those who want to test excellent work of @Anticimex and @Tekka, I have posted a simple/basic not expensive, 1.8$ for 3 breakouts here : https://oshpark.com/shared_projects/lvvxsHSW . It can be useful for existing nodes too.See you soon
-
@scalz said:
Just to say, that I tried some weeks ago ATSHA204A with pro mini and had no problem too. Maybe you should try clear eeprom and retry. Or try with another pro mini. But it should work I think.
And for those who want to test excellent work of @Anticimex and @Tekka, I have posted a simple/basic not expensive, 1.8$ for 3 breakouts here : https://oshpark.com/shared_projects/lvvxsHSW . It can be useful for existing nodes too.Good idea - I'm finding soldering the ATSHA chips to be a real pain and a small breakout board would help with that. Is the eeprom pads on your board for people who are just using a mega328 chip? Doesn't a pro-mini already have enough eeprom on board?
-
@TDD22057: eeprom on the breakout is for the new ota in Mysensors (over the air upload sketch) . It is not related to authentication.
I made this cheap breakout firstly because I wanted to test the new Mysensors features easily. and I thought it could be useful in some specific case where you don't need to make a pcb for one specific usercase so you use a veroboard and so you can easily add these new features with less pain...
Happy it can help some people
-
Regarding my issue with the ATSHA204A, I did some testing with the following results. I soldered the ATSHA204A on a small breakout board and loaded the SHAPersonalizer sketch.
I tested three configurations:
- Breakout wired to the ProMini without breadboard use
- Breakout wired to a breadboard where the ProMini was plugged
- Breakout and ProMini both plugged to breadboard and connected by wires.
Config 3 does not work!!!
That means the breadboard significantly changes the electrical characteristics. Is anybody on the forum who is able to explain that?
-
@tomkxy: it is strange. My first tests have been done in you config 3 (atsha breakout and promini both plugged to breadboard). And it worked well for me. Could it be your wire quality??? I had problems with some Dupont wire once...
-
Well , could be... I had to use different wires female - female, male - female, male - male (for config 3). For the male-male wire I have no other option at the moment.
However, I am glad it works now.
-
@tomkxy said:
Well , could be... I had to use different wires female - female, male - female, male - male (for config 3). For the male-male wire I have no other option at the moment.
However, I am glad it works now.
Good news! Regarding breadboard issues, it could be that you need an additional decoupling on the VCC line to the atsha204a. And also perhaps a pullup on the SDA signal. Breadboards usually put some more requirements on noise suppression.
-
Hi,
I seem to be too stupid (or drunk ) to get this working with MySigningAtsha204Soft
Is anyone willing to provide a working MyConfig.h and EthernetGateway.ino for this?
There seemed to be some changes and I am sure, I am just too dumb...
-
Here you go....However, I do not have EthernetGateway but a MQTTClientGateway. May be it is of help.
What is your specific problem?myconfig.h (key changed)
/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ #ifndef MyConfig_h #define MyConfig_h #include <stdint.h> // Enable debug flag for debug prints. This will add a lot to the size of the final sketch but good // to see what is actually is happening when developing #define DEBUG // Serial output baud rate (for debug prints and serial gateway) #define BAUD_RATE 115200 /********************************** * Over the air firmware updates ***********************************/ // The following define enables the safe over-the-air firmware update feature // which requires external flash and the DualOptiBoot bootloader. // Note: You can still have OTA FW updates without external flash but it // requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE //#define MY_OTA_FIRMWARE_FEATURE // Slave select pin for external flash #define MY_OTA_FLASH_SS 8 // Flash jdecid #define MY_OTA_FLASH_JDECID 0x1F65 /********************************** * Information LEDs blinking ***********************************/ // This feature enables LEDs blinking on message receive, transmit // or if some error occured. This was commonly used only in gateways, // but now can be used in any sensor node. Also the LEDs can now be // disabled in the gateway. //#define WITH_LEDS_BLINKING // The following setting allows you to inverse the blinking feature WITH_LEDS_BLINKING // When WITH_LEDS_BLINKING_INVERSE is enabled LEDSs are normally turned on and switches // off when blinking //#define WITH_LEDS_BLINKING_INVERSE // default LEDs blinking period in milliseconds #define DEFAULT_LED_BLINK_PERIOD 300 // The RX LED default pin #define DEFAULT_RX_LED_PIN 6 // The TX LED default pin #define DEFAULT_TX_LED_PIN 5 // The Error LED default pin #define DEFAULT_ERR_LED_PIN 4 /********************************** * Message Signing Settings ***********************************/ // Disable to completly disable signing functionality in library #define MY_SIGNING_FEATURE // Define a suitable timeout for a signature verification session // Consider the turnaround from a nonce being generated to a signed message being received // which might vary, especially in networks with many hops. 5s ought to be enough for anyone. #define MY_VERIFICATION_TIMEOUT_MS 5000 // Enable to turn on whitelisting // When enabled, a signing node will salt the signature with it's unique signature and nodeId. // The verifying node will look up the sender in a local table of trusted nodes and // do the corresponding salting in order to verify the signature. // For this reason, if whitelisting is enabled on one of the nodes in a sign-verify pair, both // nodes have to implement whitelisting for this to work. // Note that a node can still transmit a non-salted message (i.e. have whitelisting disabled) // to a node that has whitelisting enabled (assuming the receiver does not have a matching entry // for the sender in it's whitelist) //#define MY_SECURE_NODE_WHITELISTING // MySigningAtsha204 default setting #define MY_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached // MySigningAtsha204Soft default settings #define MY_RANDOMSEED_PIN 7 // A7 - Pin used for random generation (do not connect anything to this) // Key to use for HMAC calculation in MySigningAtsha204Soft (32 bytes) #define MY_HMAC_KEY 0x10,0x23,0xBB,0x78,0x77,0x35,0xB0,0x01,0x70,0x47,0xF1,0xDE,0x21,0x94,0x54,0x67,0xEE,0x36,0x72,0x00,0x97,0x12,0xA0,0x0A,0x0F,0x09,0x03,0xE2,0x00,0x31,0xE4,0x41 /********************************** * NRF24L01 Driver Defaults ***********************************/ #define RF24_CE_PIN 9 #define RF24_CS_PIN 10 #define RF24_PA_LEVEL RF24_PA_MAX #define RF24_PA_LEVEL_GW RF24_PA_LOW // RF channel for the sensor net, 0-127 #define RF24_CHANNEL 76 //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps #define RF24_DATARATE RF24_250KBPS // This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network. #define RF24_BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL) // Enable SOFTSPI for NRF24L01 when using the W5100 Ethernet module //#define SOFTSPI #ifdef SOFTSPI // Define the soft SPI pins used for NRF radio const uint8_t SOFT_SPI_MISO_PIN = 16; const uint8_t SOFT_SPI_MOSI_PIN = 15; const uint8_t SOFT_SPI_SCK_PIN = 14; #endif /********************************** * RFM69 Driver Defaults ***********************************/ // Default network id. Use the same for all nodes that will talk to each other #define RFM69_NETWORKID 100 // Default frequency to use. This must match the hardware version of the RFM69 radio (uncomment one): // #define RFM69_FREQUENCY RF69_433MHZ #define RFM69_FREQUENCY RF69_868MHZ //#define FREQUENCY RF69_915MHZ // Enable this for encryption of packets //#define RFM69_ENABLE_ENCRYPTION #define RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! #endif
/* MyMQTT Client Gateway 0.1b Created by Norbert Truchsess <norbert.truchsess@t-online.de> Based on MyMQTT-broker gateway created by Daniel Wiegert <daniel.wiegert@gmail.com> Based on MySensors Ethernet Gateway by Henrik Ekblad <henrik.ekblad@gmail.com> http://www.mysensors.org Requires MySensors lib 1.4b * Change below; TCP_IP, TCP_PORT, TCP_MAC This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. *1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. *2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 * Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h! define TCPDUMP and connect serial interface if you have problems, please write on http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to turn on DEBUG in libraries\MySensors\MyConfig.h also. MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition. If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20. To disable: set MQTT_FIRST_SENSORID to 255. MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like. MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes. This can be useful if you want to send latest state back to the MQTT client. Just check if incoming message has any length or not. Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. * Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType] NodeID and SensorID is uint8 (0-255) number. Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions. User can change this to their needs. We have also left some space for custom types. Special: (sensor 255 reserved for special commands) You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version) To-do: Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself. Be able to send ACK so client returns the data being sent. ... Please come with ideas! What to do with publish messages. Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation) - http://www.openhab.org/ - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en ... Please notify me if you use this broker with other software. * How to set-up Openhab and MQTTGateway: http://forum.mysensors.org/topic/303/mqtt-broker-gateway Changes by Thomas Krebs <thkrebs@gmx.de> - Add signing support from MySensors 1.5 and update for MySensors 1.5; - Restructured code back to a C like implementation following the existing MQTTGateway */ #include <SPI.h> #include <MySensor.h> #include "MyMQTTClient.h" #include "PubSubClient.h" #include <Ethernet.h> #include <DigitalIO.h> #include <MsTimer2.h> #include <Time.h> #ifdef MY_SIGNING_FEATURE #include <MySigningNone.h> #include <MySigningAtsha204Soft.h> #include <MySigningAtsha204.h> #endif //#define DSRTC #ifdef DSRTC #include <Wire.h> #include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t #endif /* * To configure MQTTClientGateway.ino to use an ENC28J60 based board include * 'UIPEthernet.h' (SPI.h required for MySensors anyway). The UIPEthernet-library can be downloaded * from: https://github.com/ntruchsess/arduino_uip */ //#include <UIPEthernet.h> /* * To execute MQTTClientGateway.ino on Yun uncomment Bridge.h and YunClient.h. * Do not include Ethernet.h or SPI.h in this case. * On Yun there's no need to configure local_ip and mac in the sketch * as this is configured on the linux-side of Yun. */ //#include <Bridge.h> //#include <YunClient.h> // * Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above! /* #define RADIO_CE_PIN 3 // radio chip enable #define RADIO_SPI_SS_PIN 8 // radio SPI serial select #define RADIO_ERROR_LED_PIN A2 // Error led pin #define RADIO_RX_LED_PIN A1 // Receive led pin #define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/ // * Use this for default configured pro mini / nano etc : // //#define RADIO_CE_PIN 5 // radio chip enable //#define RADIO_SPI_SS_PIN 6 // radio SPI serial select //#define RADIO_ERROR_LED_PIN 7 // Error led pin //#define RADIO_RX_LED_PIN 8 // Receive led pin //#define RADIO_TX_LED_PIN 9 // the PCB, on board LED*/ // CE_PIN and SPI_SS_PIN for Mega #define RADIO_CE_PIN 48 // radio chip enable #define RADIO_SPI_SS_PIN 49 // radio SPI serial select #define RADIO_ERROR_LED_PIN A2 // Error led pin #define RADIO_RX_LED_PIN A1 // Receive led pin #define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/ //replace with ip of server you want to connect to, comment out if using 'remote_host' uint8_t remote_ip[] = { 192, 168, 178, 74 }; // Mosquitto broker //replace with hostname of server you want to connect to, comment out if using 'remote_ip' //char* remote_ip = "server.local"; //replace with the port that your server is listening on #define remote_port 1883 //replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun uint8_t local_ip[] = {192, 168, 178, 11}; //replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun uint8_t mac[] = { 0xA2, 0xAE, 0xAD, 0xA0, 0xA0, 0xA2 }; ////////////////////////////////////////////////////////////////// #if defined remote_ip && defined remote_host #error "cannot define both remote_ip and remote_host at the same time!" #endif #ifdef _YUN_CLIENT_H_ YunClient ethClient; #else EthernetClient ethClient; #endif //////////////////////////////////////////////////////////////// // NRFRF24L01 radio driver (set low transmit power by default) MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); //MyTransportRFM69 transport; // Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) //MySigningNone signer; MySigningAtsha204Soft signer; //MySigningAtsha204 signer; // Hardware profile MyHwATMega328 hw; MyMessage msg; char convBuf[MAX_PAYLOAD * 2 + 1]; uint8_t buffsize; char buffer[MQTT_MAX_PACKET_SIZE]; //////////////////////////////////////////////////////////////// volatile uint8_t countRx; volatile uint8_t countTx; volatile uint8_t countErr; //////////////////////////////////////////////////////////////// void processMQTTMessages(char* topic, byte* payload, unsigned int length); PubSubClient client(remote_ip, remote_port, processMQTTMessages, ethClient); //////////////////////////////////////////////////////////////// // Declare and initialize MySensor instance // Construct MyMQTTClient (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h, if signing // feature not to be used, uncomment) // To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h MySensor gw(transport, hw #ifdef MY_SIGNING_FEATURE , signer #endif #ifdef WITH_LEDS_BLINKING , RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN #endif ); /* * setup */ void setup() { countRx = 0; countTx = 0; countErr = 0; Ethernet.begin(mac, local_ip); //Bridge.begin(); delay(1000); // Wait for Ethernet to get configured. begin(); } /* * loop */ void loop() { if (!client.connected()) { client.connect("MySensor"); client.subscribe(MQTT_TOPIC_MASK); } client.loop(); gw.process(); } /* * processRadioMessage * * Receives radio message, parses it and forwards it to the MQTT broker */ void processRadioMessage(const MyMessage &message) { rxBlink(1); sendMQTT(message); } /* * sendMQTT * Handles processing of radio messages and eventually publishes it to the MQTT broker */ void sendMQTT(const MyMessage &inMsg) { MyMessage msg = inMsg; buffsize = 0; if (!client.connected()) return; //We have no connections - return if (msg.isAck()) { #ifdef DEBUG Serial.println("msg is ack!"); #endif if (msg.sender == 255 && mGetCommand(msg) == C_INTERNAL && msg.type == I_ID_REQUEST) { // TODO: sending ACK request on id_response fucks node up. doesn't work. // The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. } } else { // we have to check every message if its a newly assigned id or not. // Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable. uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS) + 1; if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; if (msg.sender == newNodeID) { gw.saveState(EEPROM_LATEST_NODE_ADDRESS, newNodeID); } if (mGetCommand(msg) == C_INTERNAL) { if (msg.type == I_CONFIG) { txBlink(1); if (!gw.sendRoute( build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, I_CONFIG, 0).set("M"))) errBlink(1); } else if (msg.type == I_TIME) { #ifdef DEBUG Serial.println("I_TIME requested!"); #endif txBlink(1); if (!gw.sendRoute( build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, I_TIME, 0).set(now()))) errBlink(1); } else if (msg.type == I_ID_REQUEST && msg.sender == 255) { uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS) + 1; if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; if (newNodeID >= MQTT_LAST_SENSORID) return; // Sorry no more id's left :( txBlink(1); if (!gw.sendRoute( build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, I_ID_RESPONSE, 0).set(newNodeID))) errBlink(1); } else if (msg.type == I_BATTERY_LEVEL) { strcpy_P(buffer, mqtt_prefix); buffsize += strlen_P(mqtt_prefix); buffsize += sprintf(&buffer[buffsize], "/%i/255/BATTERY_LEVEL\0", msg.sender ); msg.getString(convBuf); #ifdef DEBUG Serial.print("publish: "); Serial.print((char*) buffer); Serial.print(" "); Serial.println((char*) convBuf); #endif client.publish(buffer, convBuf); } else if (msg.type == I_SKETCH_NAME) { strcpy_P(buffer, mqtt_prefix); buffsize += strlen_P(mqtt_prefix); buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_NAME\0", msg.sender ); msg.getString(convBuf); #ifdef DEBUG Serial.print("publish: "); Serial.print((char*) buffer); Serial.print(" "); Serial.println((char*) convBuf); #endif client.publish(buffer, convBuf); } else if (msg.type == I_SKETCH_VERSION) { strcpy_P(buffer, mqtt_prefix); buffsize += strlen_P(mqtt_prefix); buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_VERSION\0", msg.sender ); msg.getString(convBuf); #ifdef DEBUG Serial.print("publish: "); Serial.print((char*) buffer); Serial.print(" "); Serial.println((char*) convBuf); #endif client.publish(buffer, convBuf); } } else if (mGetCommand(msg) != 0) { if (mGetCommand(msg) == 3) msg.type = msg.type + (S_FIRSTCUSTOM - 10); //Special message if (msg.type > VAR_TOTAL) msg.type = VAR_TOTAL; // If type > defined types set to unknown. strcpy_P(buffer, mqtt_prefix); buffsize += strlen_P(mqtt_prefix); buffsize += sprintf(&buffer[buffsize], "/%i/%i/V_%s\0", msg.sender, msg.sensor, getType(convBuf, &VAR_Type[msg.type])); msg.getString(convBuf); #ifdef DEBUG Serial.print("publish: "); Serial.print((char*) buffer); Serial.print(" "); Serial.println((char*) convBuf); #endif client.publish(buffer, convBuf); } } } /* * build * Constructs a radio message */ inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { msg.destination = destination; msg.sender = sender; msg.sensor = sensor; msg.type = type; mSetCommand(msg, command); mSetRequestAck(msg, enableAck); mSetAck(msg, false); return msg; } /* * getType */ char *getType(char *b, const char **index) { char *q = b; char *p = (char *) pgm_read_word(index); while (*q++ = pgm_read_byte(p++)) ; *q = 0; return b; } /* * begin * wraps MySensors begin method; setup of RTC and led timers interrupt */ void begin() { #ifdef DEBUG Serial.begin(BAUD_RATE); #endif #ifdef DSRTC // Attach RTC setSyncProvider(RTC.get); // the function to get the time from the RTC setSyncInterval(60); #endif gw.begin(processRadioMessage, 0, true, 0); MsTimer2::set(200, ledTimersInterrupt); MsTimer2::start(); #ifdef DEBUG Serial.print(getType(convBuf, &VAR_Type[S_FIRSTCUSTOM])); #endif } /* * processMQTTMessages * message handler for the PubSubClient */ void processMQTTMessages(char* topic, byte* payload, unsigned int length) { processMQTTMessage(topic, payload, length); } /* * processMQTTMessage * processes MQTT messages, parses the topic, extracts radio address out of topic and sends them * to the respective radio */ void processMQTTMessage(char* topic, byte* payload, unsigned int length) { char *str, *p; uint8_t i = 0; buffer[0] = 0; buffsize = 0; uint8_t cmd = -1; for (str = strtok_r(topic, "/", &p); str && i < 5; str = strtok_r(NULL, "/", &p)) { switch (i) { case 0: { if (strcmp_P(str, mqtt_prefix) != 0) { //look for MQTT_PREFIX return; //Message not for us or malformatted! } break; } case 1: { msg.destination = atoi(str); //NodeID break; } case 2: { msg.sensor = atoi(str); //SensorID break; } case 3: { char match = 0; //SensorType //strcpy(str,(char*)&str[2]); //Strip VAR_ for (uint8_t j = 0; strcpy_P(convBuf, (char*) pgm_read_word(&(VAR_Type[j]))); j++) { if (strcmp((char*) &str[2], convBuf) == 0) { //Strip VAR_ and compare match = j; break; } if (j >= VAR_TOTAL) { // No match found! match = VAR_TOTAL; // last item. break; } } msg.type = match; break; } case 4: { // support the command get and set; get will be mapped to a C_REQ and set to C_SET if (strcmp(str,MQTT_CMD_SET) == 0) { cmd = C_SET; } else if (strcmp(str,MQTT_CMD_GET) == 0) { cmd = C_REQ; } else { #ifdef DEBUG Serial.print("Received unsupported command - ignore: "); Serial.println(str); #endif } } } i++; } //Check if packge has payload if (cmd != -1) { char* ca; ca = (char *)payload; ca += length; *ca = '\0'; msg.set((const char*)payload); //Payload txBlink(1); // inject time if ((msg.destination == 0) && (msg.sensor == 199)) { unsigned long epoch = atol((char*)payload); if (epoch > 10000) { #ifdef DSRTC RTC.set(epoch); // this sets the RTC to the time from controller - which we do want periodically #endif setTime(epoch); } #ifdef DEBUG Serial.print("Time recieved "); Serial.println(epoch); #endif } // if (!gw.sendRoute( build(msg, GATEWAY_ADDRESS, msg.destination, msg.sensor, C_SET, msg.type, 0))) errBlink(1); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Led handling ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * ledTimersIntterupt */ void ledTimersInterrupt() { if (countRx && countRx != 255) { // switch led on digitalWrite(RADIO_RX_LED_PIN, LOW); } else if (!countRx) { // switching off digitalWrite(RADIO_RX_LED_PIN, HIGH); } if (countRx != 255) { countRx--; } if (countTx && countTx != 255) { // switch led on digitalWrite(RADIO_TX_LED_PIN, LOW); } else if (!countTx) { // switching off digitalWrite(RADIO_TX_LED_PIN, HIGH); } if (countTx != 255) { countTx--; } if (countErr && countErr != 255) { // switch led on digitalWrite(RADIO_ERROR_LED_PIN, LOW); } else if (!countErr) { // switching off digitalWrite(RADIO_ERROR_LED_PIN, HIGH); } if (countErr != 255) { countErr--; } } void rxBlink(uint8_t cnt) { if (countRx == 255) { countRx = cnt; } } void txBlink(uint8_t cnt) { if (countTx == 255) { countTx = cnt; } } void errBlink(uint8_t cnt) { if (countErr == 255) { countErr = cnt; } }
-
@tomkxy Thanks, that helped! I seemed to have two problems:
- I did not know where to place the necessary includes! Thanks for the examples! Helped me a lot
2)Regarding my problems from above (error: 'DEFAULT_CE_PIN' was not declared in this scope): I removed the whole libraries/MySensors dir and copied it again from the recent devel branch - this helped, error is gone and everything is compiling fine now
Thanks again and cheers,
Otto
-
@otto001 Great! And thanks @tomkxy for helping out. MySensors teamwork at it's best. This is what it's all about
-
Hi again,
and thanks again. signing seems to work now, unfortunately the sketch is too big for an UNO and I am right now struggling with the pinout and code adaptions to get it working with my W5100 shield and a mega...
/edit: got it working.MyConfig.h: #ifdef SOFTSPI // Define the soft SPI pins used for NRF radio //MEGA const uint8_t SOFT_SPI_MISO_PIN = 15; const uint8_t SOFT_SPI_MOSI_PIN = 14; const uint8_t SOFT_SPI_SCK_PIN = 16; #endif EthernetGateway.ino: #define RADIO_CE_PIN 35 // 5 // radio chip enable #define RADIO_SPI_SS_PIN 34 // 6 // radio SPI serial select
And exactly those pins I connected from radio to the mega... (just in case that anyone else is in need of this)
Might be a little OT, but maybe someone here knows a solution for a strange problem:
Whenever I am using an UNO or MEGA with my W5100 shield, I have to reset after every power-on to make the sketch run. Does anyone know this? Is there a solution? I am trying to adapt optiboot to wait additional 500ms when powering on, but no luck so far...Cheers,
Otto