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
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.
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.
New default pin is A3.
New option to skip UART confirmation: SKIP_UART_CONFIRMATION
This option prohibits the possibility to auto-generate key as there
will probably not be a way to show the generated key to the user.
More copy+paste friendly serial output of the generated key for
insertion into personalization sketch.
In a gateway, I_FIND_PARENT_RESPONSE messages was returning as true by
process(). With this commit it will return as false, is this the right
expected behavior?