For information on how to configure and use signing, please refer to the API documentation site. Occasionally, significant changes are introduced on the beta track (the development branch). For this reason the documentation for signing is kept with the sources to ensure it is always up to date with the code. You will find the documentation for the latest official release here and the documentation for the latest beta here.
Below is some background and theoretical information.
Background and concepts
Suppose two participants, Alice and Bob, wants to exchange a message. Alice sends a message to Bob. In MySensors “language” Alice could be a gateway and Bob an actuator (light swich, electronic lock, etc). But to be generic, we will substitute the term “gateway” with Alice and a “node” with Bob (although the reverse relationship is also supported).
Alice sends a message to Bob. This message can be heard by anyone who wants to listen (and also by anyone that is within “hearing” distance). Normally, this is perhaps not a big issue. Nothing Alice says to Bob may be secret or sensitive in any way. However, sometimes (or perhaps always) Bob want to be sure that the message Bob receives actually came from Alice. In cryptography, this is known as authenticity. Bob needs some way of determining that the message is authentic from Alice, when Bob receives it. This prevents an eavesdropper, Eve, to trick Bob into thinking it was Alice that sent a message Eve in fact transmitted. Bob also needs to know how to determine if the message has been repeated. Eve could record a message sent by Alice that Bob accepted and then send the same message again. Eve could also in some way prevent Bob from receiving the message and delay it in order to permit the message to arrive to Bob at a time Eve chooses, instead of Alice. Such an attack is known as a replay attack. Authenticity permits Bob to determine if Alice is the true sender of a message.
It can also be interesting for Bob to know that the message Alice sent has not been tampered with in any way. This is the integrity of the message. We now introduce Mallory, who could be intercepting the communication between Alice and Bob and replace some parts of the message but keeping the parts that authenticate the message. That way, Bob still trusts Alice to be the source, but the contents of the message was not the content Alice sent. Bob needs to be able to determine that the contents of the message was not altered after Alice sent it. Mallory would in this case be a man-in-the-middle attacker. Integrity permits Bob to verify that the messages received from Alice has not been tampered with. This is achieved by adding a signature to the message, which Bob can inspect to validate that Alice is the author.
The signing scheme used, needs to address both these attack scenarios. Neither Eve nor Mallory must be permitted to interfere with the message exchange between Alice and Bob.
The key challenge to implementing a secure signing scheme is to ensure that every signature is different, even if the message is not. If not, replay attacks would be very hard to prevent. One way of doing this is to increment some counter on the sender side and include it in the signature. This is however predictable. A better option would be to introduce a random number to the signature. That way, it is impossible to predict what the signature will be. The problem is, that also makes it impossible for the receiver (Bob) to verify that the signature is valid. A solution to this is to let Bob generate the random number, keep it in memory and send it to Alice. Alice can then use the random number in the signature calculation and send the signed message back to Bob who can validate the signature with the random number used. This random number is in cryptography known as a nonce or salt.
However, Mallory might be eavesdropping on the communication and snoop up the nonce in order to generate a new valid signature for a different message. To counter this, both Alice and Bob keep a secret that only they know. This secret is never transmitted over the air, nor is it revealed to anybody. This secret is known as a pre-shared key (PSK).
If Eve or Mallory are really sophisticated, he/she might use a delayed replay attack. This can be done by allowing Bob to transmit a nonce to Alice. But when Alice transmits the uniquely signed message, Mallory prevents Bob from receiving it, to a point when Mallory decides Bob should receive it. An example of such an attack is described here. This needs to be addressed as well, and one way of doing this is to have Bob keep track of time between a transmitted nonce and a signed message to verify. If Bob is asked for a nonce, Bob knows that a signed message is going to arrive “soon”. Bob can then decide that if the signed message does not arrive within a predefined timeframe, Bob throws away the generated nonce and thus makes it impossible to verify the message if it arrives late.
The flow can be described like this:
The benefits for MySensors to support this are obvious. Nobody wants others to be able to control or manipulate any actuators in their home.
Why encryption is not part of this
Well, some could be uncomfortable with somebody being able to snoop temperatures, motion or the state changes of locks in the environment. Signing does not address these issues. Encryption is needed to prevent this. It is my personal standpoint that encryption should not be part of the MySensors “protocol”. The reason is that a gateway and a node does not really care about messages being readable or not by “others”. It makes more sense that such guarantees are provided by the underlying transmission layer (RF solution in this case). It is the information transmitted over the air that needs to be secret (if user so desires). The “trust” level on the other hand needs to go all the way into the sketches (who might have different requirements of trust depending on the message participant), and for this reason, it is more important (and less complicated) to ensure authenticity and integrity at protocol-level as message contents is still readable throughout the protocol stack. But as soon as the message leaves the “stack” it can be scramble into “garbage” when transmitted over the air and then reassembled by a receiving node before being fed in “the clear” up the stack at the receiving end.
There are methods and possibilities to provide encryption also in software, but if this is done, it is my recommendation that this is done after integrity- and authentication information has been provided to the message (if this is desired). Integrity and authentication is of course not mandatory and some might be happy with only having encryption to cover their need for security. I, however, have only focused on integrity and authenticity while at the same time keeping the current message routing mechanisms intact and therefore leave the matter of secrecy to be implemented in the “physical” transport layer. With the integrity and authenticity handled in the protocol it ought to be enough for a simple encryption (nonce-less AES with a PSK for instance) on the message as it is sent to the RF backend. Atmel does provide such circuits as well but I have not investigated the matter further as it given the current size of the ethernet gateway sketch is close to the size limit on an Arduino Nano, so it will be difficult to fit this into some existing gateway designs. Also it is worth to consider that the state of a lock can just as readily be determined by simply looking at the door in question or attempting to open it, so obfuscating this information will not necessarily deter an attacker in any way. Nevertheless, I do acknowledge that people find the fact that all information is sent “in the clear” even if it require some technical effort for an intruder to obtain and inspect this information. So I do encourage the use of encrypting transport layers. This is however not covered by this implementation.
How this is done
There exist many forms of message signature solutions to combat Eve and Mallory. Most of these solutions are quite complex in term of computations, so I elected to use an algorithm that an external circuit is able to process. This has the added benefit of protecting any keys and intermediate data used for calculating the signature so that even if someone were to actually steal a sensor and disassembled it, they would not be able to extract the keys and other information from the device. A common scheme for message signing (authenticity and integrity) is implemented using HMAC which in combination with a strong hash function provides a very strong level of protection. The Atmel ATSHA204A is a low-cost, low-voltage/current circuit that provides HMAC calculation capabilities with SHA256 hashing which is a (currently) virtually unbreakable combination. If SHA256 were to be hacked, a certain cryptocurrency would immediately be rendered worthless. The ATSHA device also contain a random number generator (RNG) which enables the generation of a good nonce, as in, non-predictable. As I acknowledge that some might not want to use an additional external circuit, I have also implemented a software version of the ATSHA device, capable of generating the same signatures as the ATSHA device does. Because it is pure-software however, it does not provide as good nonces (it uses the Arduino pseudo-random generator) and the HMAC key is stored in SW and is therefore readable if the memory is dumped. It also naturally claims more flash space due to the more complex software. But for indoor sensors/actuators this might be good enough for most people.
The technical stuff
How are the messages actually affected by the signing? The following illustration shows what part of the message is signed, and where the signature is stored:
The first byte of the header is not covered by the signature, because in the network, this byte is used to track hops in the network and therefore might change if the message is passing a relay node. So it cannot be part of the signature, or the signature would be invalid when it arrives to its destination. The signature also carries a byte with a signing identifier to prevent false results from accidental mixing of incompatible signing backends in the network. Thus, the maximum size for a payload is 29-7 bytes. Larger payloads are not possible to sign. Another thing to consider is that the strength of the signature is inversely proportional to the payload size.
As for the software backend, it turns out that the ATSHA does not do “vanilla” HMAC processing. Fortunately, Atmel has documented exactly how the circuit processes the data and hashes thus making it possible to generate signatures that are identical to signatures generated by the circuit.
The signatures are calculates in the following way:
Exactly how this is done can be reviewd in the source for the ATSHA204SOFT backend and the ATSHA204A datasheet. In the MySensors protocol, the following internal messagetypes handles signature requirements and nonce requests: I_SIGNING_PRESENTATION I_NONCE_REQUEST I_NONCE_RESPONSE
Also, the version field in the header has been reduced from 3 to 2 bits in order to fit a single bit to indicate that a message is signed.
Due to the limiting factor of our cheapest Arduino nodes, the use of diversified keys is not implemented. That mean that all nodes in your network share the same PSK (at least the ones that are supposed to exchange signed data). It is important to understand the implications of this, and that is covered in the "Typical use cases" chapter below. Also be reminded that the strength of the signature is inversely proportional to the size of the message. The larger the message, the weaker the signature.