Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signing support for MySensors #71

Merged
merged 7 commits into from Feb 18, 2015

Conversation

Projects
None yet
2 participants
@fallberg
Copy link
Contributor

fallberg commented Feb 17, 2015

This PR contains the necessary changes to enable signed message exchange for the MySensors framework.
By default, all sketches will get a "dummy" signing implementation. However, sketches will not pass signed messages "by default".
Two more backends are provided; One that provides "enterprise level" security using Atmel ATSHA204 and one that emulates the ATSHA204 in software. The emulated backend does not provide the same "enterprise level" of security, but it can both provide and verify signed messages with nodes that does have a real ATSHA204 circuit. For nodes that are kept safe from prying eyes and memory dumpers, the emulated backend should be safe to use (in other words, put these locked indoors).

Full description of implementation, protocol and usage will be posted on the MySensors forum.

fallberg added some commits Feb 5, 2015

Message header updates for signing support
One bit in the protocol version field is converted to a sign
indicator. '1' means the message carries a signature in the
unused part of the payload data buffer.

Three new internal message types have been defined:

 * I_REQUEST_SIGNING    carries a boolean and is used to exchange
                        signing requirement information between
                        nodes.
                        If the I_REQUEST_SIGNING carries 'true'
                        the receiver is informed that the sender
                        require properly signed messages in order
                        to be able to accept the messages.
 * I_GET_NONCE          is passed from sender to a receiver that
                        require signing tellig it to submit a
                        cryptographic 'nonce' that the sender needs
                        in order to be able to sign the message it
                        intend to send. The I_GET_NONCE carries no
                        payload.
 * I_GET_NONCE_RESPONSE is sent by the receiver of a signed
                        message in response to I_GET_NONCE.
                        The first byte of the payload is a signing
                        identifier informing the sender of the
                        signed message about the type of signature
                        the receiver is expecting.
Signing driver framework
The signing driver framework resembles the radio driver framework
in the sense that it relies on MyConfig.h for driver specific
settings. This allows the constructor to be clean and the API less
likely to need change.

The API is designed with function pairs for sender and receiver of
a signed message.
The sender of a signed message uses putNonce() and signMsg()
and the receiver of a signed message uses getNonce() and
verifyMsg().
In addition, receiver is expected to call checkTimer() at regular
intervals to make sure the message session does not time out.

The program flow is that the sender transmit, after determining
that the message needs signing, a request to the receiver for a
nonce (I_GET_NONCE). The receiver calls getNonce() to obtain a
nonce and transmits the nonce back to the sender
(I_GET_NONCE_RESPONSE).
The sender stores the received nonce in the driver with putNonce()
and then calls signMsg() to sign the message to be transmitted.
The receiver then calls verifyMsg() to authenticate the signed
message using the nonce transmitted earlier.

The flow is described below:
---------------- --------            ---------- ------------------
|senders driver| |sender|            |receiver| |receivers driver|
---------------- --------            ---------- ------------------
        |            |    I_GET_NONCE     |  getNonce()  |
        |            |------------------->|------------->|
        |            |                    |              |
        | setNonce() |I_GET_NONCE_RESPONSE|              |
        |<-----------|<-------------------|<-------------|
        | signMsg()  |                    |              |
        |<-----------|                    | verifyMsg()  |
        |----------->|------------------->|------------->|
        |            |                    | OK / not OK  |
        |            |                    |<-------------|

It is expected that all signing schemes is built upon this
principle.
Dummy signing driver backend
The dummy signing driver implements the most rudimentary form of
signing. No pre-shared key is used, nonce is simply incremeted
each turn and signature is only calculated on the fist byte using
data XOR nonce.
This driver is intended for library debugging and sensor network
integrity verification (signed messages will force the radio to
transmit all 32 bytes of data).
It does check SIGNING_IDENTIFIER byte to avoid illegal mixing of
signing backends in the network (as seen by this node) and it does
verify proper execution order on the API.
The dummy driver rejects all other signing backend protocols.

Signing backend is selected in MyConfig.h
ATSHA204 signing backend
Default SDA pin is A3 for single wire communication.
The pin is selected in MyConfig.h.
I2C variant of ATSHA204 is not supported.

Messages are signed using HMAC-SHA256 where some parts of the
message digest are ATSHA204 specific.
ATSHA204 emulated signing backend
ATSHA204 emulated signing backend. The emulated ATSHA204
implementation offers pseudo random number generation and
HMAC-SHA256 authentication compatible with a "physical"
ATSHA204.

NOTE: Key is stored in clear text in the Arduino firmware.
Therefore, the use of this back-end could compromise the key
used in the signed message infrastructure if device is lost
and its memory dumped.

The seed for the random number generated is sampled from an
analog pin. The pin is set in MyConfig.h using RANDOMSEED_PIN.
The pin should be unconnected.

The key to use for HMAC calculations must match the key used by
other nodes this node will exchange signed messages with. The key
for ATSHA204 emulator is set in MyConfig.h using hmacKey.
Signing support implemented in the MySensors library
The dummy signing driver backend is used. But with this commit all
framework logic for managing signed messages in the MySensors
ecosystem is implemented and enables more sophisticated signing
backends to be added later on.

For a sensor (or gateway) that require a gateway to send signed
messages to it, add 'true' as the fifth argument to 'begin'.
The gateway will automatically inform a node of it's signing
requirements as soon as it receivs the nodes signing preference.
It is important to understand that if the gateway require
signing, it will in this implementation only require signing from
nodes that require signing by the gateway.

If the sensor requires signing from another node on the network
which it communicates directly with, it needs to send 'true' in
an internal message of type I_REQUEST_SIGNING.
Added example sketch for a secure actuator
The sketch closely resembles the RelayActuator example.
The difference is that this sketch require gateway to sign
all messages addressed to the actuator.

henrikekblad added a commit that referenced this pull request Feb 18, 2015

Merge pull request #71 from fallberg/sign_dev
Signing support for MySensors

@henrikekblad henrikekblad merged commit 11058f7 into mysensors:development Feb 18, 2015

@fallberg fallberg deleted the fallberg:sign_dev branch Feb 18, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.