[security] Introducing signing support to MySensors


  • Contest Winner

    Signing support has now been implemented and is available from release 1.5 of the MySensors library.
    From version 2.0.0, all documentation is managed using doxygen, and you find the most current documentation here for releases and here for development branch.
    You can find the signing documentation under "modules" and "MySensors internal APIs and functionalities > MySigning".

    In an effort to normalize the technical playing field for all forum members I will describe what this means, and why it is important. And I will also briefly touch on the generic concept of authentication and verification, motivate the need for this (and explain why encryption is not part of this) and go on to explain the architecture used for MySensors and how to enable and use this new feature.

    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 need some way of determining that the message is authentic from Alice, when Bob receives it. This prevent an eavesdropper, Eve, to trick Bob into thinking it was Alice that sent a message Eve in fact transmitted. Bob also need 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.
    alice_bob.png

    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.
    mallory.png

    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 Even 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:
    authentication.png

    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 topic nor my 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.

    How to use this

    Before we begin with the details, I just want to emphasize that signing is completely optional and although it is enabled by default, it will use a default backend that does not require signing and does not enforce signature checks. However, if you really do not want any additional "cost" in program space related to signing, you can disable MY_SIGNING_FEATURE in MyConfig.h.

    Firstly, you need to make sure MY_SIGNING_FEATURE is enabled in MyConfig.h. You then select which backend to use by passing the appropriate handle when constructing the MySensor object. The handle is passed as the third argument (example here uses the real ATSHA without whitelisting):

    #include <MySigningAtsha204.h>
    
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    MySigningAtsha204 signer; // Select HW ATSHA signing backend
    
    MySensor gw(radio, hw, signer);
    

    If the software equivalent if the ATSHA is desired instead do

    #include <MySigningAtsha204Soft.h>
    
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    
    // Change the soft_serial value to an arbitrary value for proper security
    uint8_t soft_serial[SHA204_SERIAL_SZ] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
    MySigningAtsha204Soft signer(true, 0, NULL, soft_serial);  // Select SW ATSHA signing backend
    
    MySensor gw(radio, hw, signer);
    

    It is legal to mix MySigningAtsha204 and MySigningAtsha204Soft backends in a network. They work together.

    Secondly, you need to verify the configuration for the backend. Currently, only MySigningAtsha204 and MySigningAtsha204Soft backends have a specific configuration.
    For MySigningAtsha204 it is the pin the device is connected to. In MyConfig.h there are defaults for sensors and gateways which you might need to adjust to match your personal build. The setting is defined using MY_ATSHA204_PIN and the default is to use pin A3.
    For MySigningAtsha204Soft, an unconnected analog pin is required to set a random seed for the pseudo-random generator. It is important that the pin is floating, or the output of the pseudo-random generator will be predictable, and thus compromise the signatures. The setting is defined using MY_RANDOMSEED_PIN and the default is to use pin A7.

    Thirdly, if you use the MySigningAtsha204Soft backend, you need to create/set a HMAC key to use. This key is 32 bytes wide and should be an arbitrarily chosen value. A string is OK, but as this key never needs to be “parsed” a completely random number is recommended. The key is stored in our sketch and is passed when constructing the MySigningAtsha204Soft object.

    If you use the “real” ATSHA204A, before any signing operations can be done, the device needs to be personalized. This can be a daunting process as it involves irreversibly writing configurations to the device, which cannot be undone. I have however tried to simplify the process as much as possibly by creating a helper-sketch specifically for this purpose in libraries/MySensors/examples/Sha204Personalizer/sha204_personalizer.ino

    The process of personalizing the ATSHA204A involves

    • Writing and locking chip configuration
    • (optionally) Generating and (mandatory) writing HMAC key
    • (optionally) Locking data sections

    First execute the sketch without modifications to make sure communications with the device can be established. It is highly recommended that the first time this is done, a device with serial debug possibilities is used.
    When this has been confirmed, it is time to decide what type of personalization is desired.
    There are a few options here.
    Firstly, enable LOCK_CONFIGURATION to allow the sketch to lock the chip configuration. The sketch will write the default settings to the chip because these are fine for our purposes. This also enables the RNG which is required to allow the sketch to automatically generate a PSK if this is desired.
    Now it is possible to execute the sketch to lock the configuration and enable the RNG.
    Next step is to decide if a new key should be generated or an existing key should be stored to the device. This is determined using USER_KEY_DATA, which, if defined, will use the data in the variable user_key_data.
    If USER_KEY_DATA is disabled, the RNG will be used to generate a key. This key obviously need to be made available to you so you can use it in other devices in the network, and this key is therefore also printed on the serial console when it has been generated.
    The key (generated or provided) will be written to the device unless SKIP_KEY_STORAGE is set. As long as the data zone is kept unlocked the key can be replaced at any time. However, Atmel suggests the data region to be locked for maximum security. On the other hand, they also claim that the key is not readable from the device even if the data zone remains unlocked so the need for locking the data region is optional for MySensors usage.
    For devices that does not have serial debug possibilities, it is possible to set SKIP_UART_CONFIRMATION, but it is required to set USER_KEY_DATA if this option is enabled since a generated and potentially unknown key could be written to the device and thus rendering it useless (if the data zone is also locked).
    For devices with serial debug possibilities it is recommended to not use SKIP_UART_CONFIRMATION as the sketch without that setting will ask user to send a ‘space’ character on the serial terminal before any locking operations are executed as an additional confirmation that this irreversible operation is done. However, if a number of nodes are to undergo personalization, this option can be enabled to streamline the personalization.
    This is a condensed description of settings to fully personalize and lock down a set of sensors (and gateways):
    Pick a “master” device with serial debug port.
    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_DATA

    Execute 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.
    Now reconfigure the sketch with these settings:
    Enable LOCK_CONFIGURATION
    Enable LOCK_DATA (if you are sure you do not need to replace/revoke the key, this is the most secure option to protect from key readout according to Atmel, but they also claim that key is not readable even if data region remains unlocked from the slot we are using)
    Disable SKIP_KEY_STORAGE
    Enable SKIP_UART_CONFIGURATION
    Enable USER_KEY_DATA
    Put the saved key in the user_key_data variable.

    Now execute the sketch on all devices you want to personalize with this secret key. That’s it. Personalization is done and the device is ready to execute signing operations which are valid only on your personal network.

    In case you want to be able to "whitelist" trusted nodes (in order to be able to revoke them in case they are lost) you also need to take note of the serial number of the ATSHA device. This is unique for each device. The serial number is printed in a copy+paste friendly format by the personalizer for this purpose.

    Signing in the MySensors network is driven from the receiving nodes. That means, if a node require signing it will inform the gateway of this. To instruct a node to require signing by the gateway, provide a suitable backend to the library constructor. Both MySigningAtsha204 and MySigningAtsha204Soft backends will by-default require signing when used.
    The default constructors for these backends can be overridden to disable signing requirements if the node does not require signed messages but still need the ability to verify messages (like a gateway).

    Example for a node that uses ATSHA and require signing:

    #include <MySigningAtsha204.h>
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    MySigningAtsha204 signer; // Select ATSHA204A physical signing circuit
    MySensor gw(radio, hw, signer);
    

    Example for a gateway that uses ATSHA signing in software and do not require signing from nodes:

    #include <MySigningAtsha204Soft.h>
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    uint8_t soft_serial[SHA204_SERIAL_SZ] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
    MySigningAtsha204Soft signer(false, 0, NULL, soft_serial);  // Select ATSHA204A software signing backend
    MySensor gw(radio, hw, signer);
    

    If a node does require signing, any unsigned message sent to the node will be rejected.
    This also applies to the gateway. However, the difference is that the gateway will only require signed messages from nodes it knows in turn require signed messages.
    A node can also inform a different node that it expects to receive signed messages from it. This is done by transmitting an internal message of type I_REQUEST_SIGNING and provide a boolean for payload, set to true.
    All nodes and gateways in a network maintain a table where the signing preferences of all nodes are stored. This is also stored in EEPROM so if the gateway reboots, the nodes does not have to retransmit a signing request to the gateway for the gateway to realize that the node expect signed messages.
    Also, the nodes that do not require signed messages will also inform gateway of this, so if you reprogram a node to stop require signing, the gateway will adhere to this as soon as the new node has presented itself to the gateway.

    The following sequence diagram illustrate how messages are passed in a MySensors network with respect to signing:
    authentication_mysensors.png

    None of this activity is “visible” to you (as the sensor sketch implementor). All you need to do is to set your preferences in MyConfig.h, depending on chosen backend, do personalization or key configurations and set the requestSignatures parameter to true. That is enough to enable protection from both Eve and Mallory in your network (although because of the lack of encryption, Eve can eavesdrop, but not do anything about, your messages).

    Whitelisting and node revocation

    Consider the situation when you have set up your secure topology. We use the remotely operated garage door as an example:

    • You have a node inside your garage (therefore secure and out of reach from prying eyes) that controls your garage door motor. This node require signing since you do not want an unauthorized person sending it orders to open the door.
    • You have a keyfob node with a signing backend that uses the same PSK as your door opener node.

    In this setup, your keyfob can securely transmit messages to your door node since the keyfob will sign the messages it sends and the door node will verify that these were sent from a trusted node (since it used the correct PSK). If the keyfob does not sign the messages, the door node will not accept them.

    One day your keyfob gets stolen or you lost it or it simply broke down.

    You know end up with a problem; you need some way of telling your door node that the keyfob in question cannot be trusted any more. Furthermore, you maybe locked the data region in your door nodes ATSHA device and is not able to revoke/change your PSK, or you have some other reason for not wanting to replace the PSK. How do you make sure that the "rogue" keyfob can be removed from the "trusted chain"?

    The answer to this is whitelisting. You let your door node keep a whitelist of all nodes it trusts. If you stop trusting a particular node, you remove it from the nodes whitelist, and it will no longer be able to communicate signed messages to the door node.

    This is achieved by 'salting' the signature with some node-unique information known to the receiver. In the case of ATSHA204A this is the unique serial number programmed into the circuit. This unique number is never transmitted over the air in clear text, so Eve will not be able to figure out a "trusted" serial by snooping on the traffic.
    Instead the value is hashed together with the senders NodeId into the HMAC signature to produce the final signature. The receiver will then take the originating NodeId of the signed message and do the corresponding calculation with the serial it has stored in it's whitelist if it finds a matching entry in it's whitelist.

    Whitelisting is an optional alternative because it adds some code which might not be desirable for every user. So if you want the ability to provide and use whitelists, as well as transmitting to a node with a whitelist, you need to enable MY_SECURE_NODE_WHITELISTING in MyConfig.h
    The whitelist is provided when constructing the signing backend as follows (example is a node that require signing as well):

    #include <MySigningAtsha204.h>
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    #ifdef MY_SECURE_NODE_WHITELISTING
    whitelist_entry_t node_whitelist[] = {
      { .nodeId = 55, // Just some value, this need to be changed  to the NodeId of the trusted node
        .serial = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09} } // This need to change to the serial of the trusted node
    };
    MySigningAtsha204 signer(true, 1, node_whitelist);  // Select ATSHA204A software signing backend with one entry in the whitelist
    #else
    MySigningAtsha204 signer;  // Select ATSHA204A software signing backend
    #endif
    MySensor gw(radio, hw, signer);
    

    The "soft" backend of course also support whitelisting. However, since it does not contain a unique identifier, you have to provide an additional constructor argument when you enable whitelisting as illustrated in this example:

    #include <MySigningAtsha204Soft.h>
    MyTransportNRF24 radio;  // NRFRF24L01 radio driver
    MyHwATMega328 hw; // Select AtMega328 hardware profile
    #ifdef MY_SECURE_NODE_WHITELISTING
    // Change the soft_serial value to an arbitrary value for proper security
    uint8_t soft_serial[SHA204_SERIAL_SZ] = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01};
    whitelist_entry_t node_whitelist[] = {
      { .nodeId = 55, // Just some value, this need to be changed to the NodeId of the trusted node
        .serial = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09} } // This need to change to the serial of the trusted node
    };
    MySigningAtsha204Soft signer(true, 1, node_whitelist, soft_serial);  // Select ATSHA204A software signing backend with one entry in the whitelist and our unique serial
    #else
    MySigningAtsha204 signer;  // Select ATSHA204A software signing backend
    #endif
    MySensor gw(radio, hw, signer);
    

    For a node that should transmit whitelisted messages but not receive whitelisted messages, you can simply skip the whitelist arguments (1 and node_whitelist above). For the "soft" backend, you can set these to 0 and NULL since you then need to provide the soft_serial buffer.

    It is important to emphasize that you do not have to provide a whitelist that has entries for all nodes that transmit signed messages to the node in question. You only need to have entries for the nodes that in turn have enabled MY_SECURE_NODE_WHITELISTING. Nodes that does not have this option enabled can still transmit "regular" signed messages as long as they do not match a NodeId in the receivers whitelist.

    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:
    signing-illustrated-1.gif

    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 ATSHA204SOFT 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:
    signing-illustrated-2.gif

    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 new internal messagetypes has been added for handling signature requirements and nonce requests:
    I_REQUEST_SIGNING
    I_GET_NONCE
    I_GET_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.

    Known limitations

    It is very important to emphasize that with the current implementation of message signing, OTA firmware updates are transmitted unsigned. In other words, it is technically possible for Mallory to reset a node by cutting power or some other attack, spoof a gateway and push his/her own custom firmware to the node even if the old sketch was requiring signing. The current architecture of the OTA solution prevents signing support from being implemented in the bootloader due to size constraints.
    It is still possible to use OTA bootloader with a signing gateway and node, but it is important to understand this potentially provides an attack vector for compromising the security of the node.
    Also, due to the limiting factor our our 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 hopefully covered in the "Typical usecases" 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.

    Typical usecases

    "Securely located" in this context mean a node which is not physically publicly accessible. Typically at least your gateway.
    "Public" in this context mean a node that is located outside your "trusted environment". This includes sensors located outdoors, keyfobs etc.

    Securely located lock

    You have a securely located gateway and a lock somewhere inside your "trusted environment" (e.g. inside your house door, the door to your dungeon or similar).
    You should then keep the data section of your gateway and your lock node unlocked. Locking the data (and therefore the PSK) will require you to replace at least the signing circuit in case you need to revoke the PSK because some other node in your network gets compromised.

    Patio motion sensor

    Your gateway is securely located inside your house, but your motion sensor is located outside your house. You have for some reason elected that this node should sign the messages it send to your gateway.You should lock the data (PSK) in this node then, because if someone were to steal your patio motion sensor, they could rewrite the firmware and spoof your gateway to use it to transmit a correctly signed message to your secure lock inside your house. But if you revoke your gateway (and lock) PSK the outside sensor cannot be used for this anymore. Nor can it be changed in order to do it in the future. You can also use whitelisting to revoke your lost node.
    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.

    Keyfob for garage door opener

    Perhaps the most typical usecase for signed messages. Your keyfob should be totally locked down. If the garage door opener is secured (and it should be) it can be unlocked. That way, if you loose your keyfob, you can revoke the PSK in both the opener and your gateway, thus rendering the keyfob useless without having to replace your nodes. You can also use whitelisting to revoke your lost keyfob.


  • Admin

    Thanks for all the effort you've put into this @Anticimex. This really lifts the MySensors project to new heights and applications in locks and other security devices.


  • Contest Winner

    @hek Thanks. Hope it is used, because I have not really had enough "run time" with my limited setups. Node-hops is one thing I have not been able to verify for instance, so hopefully my post de-mystifies things enough for people to try this out.


  • Mod

    @Anticimex It is a great job! And also very nice explanation

    Thanks for this!

    ATSHA204 is market by Atmel as "NOT RECOMMENDED FOR NEW DESIGNS"
    It is important to state that ATSHA204A need to be considered.


  • Admin

    nice work @Anticimex looking forward to try it out when i get more nodes up and running. Should become easier with the micro board.

    @axillent i used the atsha204a on my prototype. and the code provided by @Anticimex did find it. So no problems in using the a device (or so it seems)


  • Contest Winner

    @axillent I know, and I dont even think you can get ATSHA204 anymore. In any case it does not matter as the main difference is that ATSHA204A also allows users to do SHA256 calculations, something we don't need so we are compatible with both variants.


  • Contest Winner

    I should add that I have used ATSHA204A in all my testing (it is the only variant I have) so we should be covered on that part.



  • @Anticimex very nice work.



  • Wow, great work!



  • Awesome, when I order new boards I will include this feature. One question, does your implementation require the use of both SDA and SCL pins or just SDA? I think I prefer the larger SOT-23 package that only has SDA pin. I guess simply, one-wire or I2C?

    Thanks.


  • Contest Winner

    @therik then you're in luck 🙂 only single wire option is supported. I decided to do this because I think it is the most attractive HW option.


  • Hero Member

    @Anticimex , fantastic take. One question so far --- Is (or will be) possible to a gateway working with both signed and non-signed messages? I don't have OTA, and to re-work all my existing sensors it will demand a considerable effort.

    Having security on further sensors is anyway amazing.

    Thanks a lot!


  • Contest Winner

    @rvendrame Thanks.
    Yes. You can mix everything. You can have some nodes which require signed messages and some who does not in the same network at the same time. This should also work though relays (sign messages can pass relay nodes that are incapable of signing).
    The gateway will keep track on which nodes that require signing and which who don't, and do signing accordingly.
    So you can leisurely introduce signing only on newly added nodes or only activate it for the existing nodes that you want it on. It should even be possible to keep old nodes without reflashing their firmware (although that is a usecase I have not tested).


  • Contest Winner

    EDIT: Moved the location of the SHA204 personalizer in the first post since it has moved in the tree.
    Also, I have noticed that recent activity on development branch seem to have broken the signing support. I am investigating the issue.
    Life on the development branch is 'hard'. I am sorry about the outage, but these things are to be expected when many developers work on the same code piece and are not fully in-sync with each others activities. I will post here a SHA to a known "good" state once I have sorted the issue. I encourage all to test this out once I do, so we can get more test-coverage on this quite big feature in the library. Once we have it stabilized, it might get included in a "v1.5" of the library and then live a happy stable life on 'master' 🙂


  • Contest Winner

    Now a patch is merged to 'development' for the issue. Please give it a go. I need help in testing. I have tested it successfully with the SecureActuator sketch and the ATSHA204 signing backend.


  • Contest Winner

    @Anticimex Wow this is really good work AND explanations.

    I'm thinking about one issue: Lets assume I use a remote as garage opener. Now on a bad day I loose this remote. Is it possible to block the commands of the remote. I.e. have a blacklist like thing? Is it even possible to (in theory with the used components and in practise with the current code) to identify each SHA device? I.e. does Bob know "the message comes from someone I turst" or does he know "the messages comes from allice (which I trust)".

    Obviously I'd be unable to change the PSKs because I need to lock the PSK Memroy area... So I'd have to throw away all devices for this approach - right?

    Thanks for your great work again.


  • Contest Winner

    @Dirk_H Thanks!
    Well, the ATSHA itself does support this kind of thing. But it is difficult to make it generic enough to open up for other backends to share the same functionality. It IS possible to skip locking the data area and still have signing working though. But that obviously opens the possibility to physically attack the node and read or replace the key. However, if someone got physical access to your node, they already have physical access to your garage. So the door would already be open.
    So if we assume you skipped locking the data section of the ATSHA204 you could bring down the node and revoke the PSK by writing a new one. That would invalidate any "rouge" nodes with the old PSK.
    Personally, I do not think I will ever lock down the data section since it is anyway only by physical access to the device you can rewrite or read the PSK and with physical access to the node..well...you are pretty much owned then in any case.


  • Contest Winner

    Ok thanks for clarification Anticimex. I meant if you have a remote to open your garage and leave it in your car which e.g. gets stolen. However it good that you pointed out that locking the device is no "must". I think in many applications it might be even contraproductive.

    locking the device would only prevent the thief from copying but not from using - Which would have higher importanance in this case. Maybe this lokcing feature is generelly more used for dongle like applications.


  • Contest Winner

    @Dirk_H yes if you have a handheld device that moves about, I recommend locking it to prevent key tampering in case it is lost. That makes it a black box.
    I do understand what you mean. My point is, you have a node in the garage that is the actuator. You do not want your actuator to be tampered to accept different keys (or having the firmware replaced entirely). So you need to protect you actuator in any case. Looking the chip data in the actuator then has little benefit since if someone had access to it, they could just flash a firmware that ignores signatures.
    But your keyfob is "public" so it is the typical part you want to lock. If you loose it nobody would be able to exploit it to transmit valid signatures if you replace the key in your actuator. I will consider updating the post with a number of use cases and highlight when data locking is advisable and when it is not.


  • Contest Winner

    EDIT: I have added a "usecase" section outlining three typical usecases. In summary: keep data section unlocked on all nodes that you can guarantee will be tamper-free. Lock data area on all nodes that require (or do) signing and are located in a more "volatile" environment (where they can be stolen or tampered with).


  • Hero Member

    @Anticimex, let me try to get a holistic view:

    • I think commercial solutions like z-wave have even less security (as they are design to work across multiple vendors / solutions, so no pre-shared key). Have a look on this http://research.sensepost.com/cms/resources/conferences/2013/bh_zwave/Security Evaluation of Z-Wave_WP.pdf

    • The use case discussed here (lost garage remote): If I remove the remote from my automation software, the remote will not be able to open my garage, right? What you are saying is that if someone finds the remote, by hacking it it should be possible to obtain the pre-shared key (but it involves a considerable effort , maybe even SMD de-soldering and so)... Correct?

    • Ok, now that someone else have my pre-shared key (and assuming that I didn't change it): He/she needs to sniff into my MYS network, learn MYS protocols, monitor the traffic for some time, and with all that, it should be possible to emulate the GW telling the garage door to "open".

    • I guess the same applies to my wi-fi network --- If I loose my iphone, someone can break it and retrieve my router wi-fi password, connect into it, and unlock the door via my door lock App, right?

    Sorry if those questions sound too stupid --- I'm new to all of this things... But I think MYS is primarily targeting for home DIY users, so if we achieve the same level of a house alarm for example --- wouldn't that be enough for a first step?


  • Contest Winner

    @rvendrame In security, there are no stupid questions.
    Regarding the lost keyfob case, if we assume that you use the ATSHA204 device (not the software emulation) and you have locked the device, the PSK is unobtainable. Even if the device is picked apart, there is no way to extract the PSK from the ATSHA204 device.
    However, also assuming that you do not alter your PSK in the "receiving" end, you are still at risk, much in the same way as your car is at risk if you loose the keyfob to it.
    Also, if you use the same PSK on other parts of your system (like your GW) an attacker could pick the stolen ATSHA device and put it in their own device to allow it to transmit signed messages to any node in your system until you revoke the PSK in your GW (and corresponding nodes).
    This is unfortunate, but with the limited memory we have in the current design, it is unfeasible to have a GW (or a node) keep track on white and/or blacklisted devices. I have not been able to figure out a way of doing that with the ATSHA in a way that does not prevent a SW emulation of the feature that is acceptable enough from a security point of view.
    Basically: Keep track on your transmitting nodes.
    My ambition with the signing feature is to protect a network from external attackers. More sophisticated features are needed to also protect against attackers using your own devices against you. I would like to investigate the possibility of blacklisting further, but I only have so much time, and Arduinos only have so much memory so that is something either someone else need to investigate further (I really want to start focusing on sensors myself now) or something to be considered with more sophisticated hardware. The ATSHA204 can cover for this as well, but it will require more memory on the devices using it.

    And yes, if your controller is accessible through internet or through wifi, an attacker will most likely come from that direction, and not directly on your nodes. But "MySensors" cannot cover security in those areas.


  • Hero Member

    @Anticimex said:

    Also, if you use the same PSK on other parts of your system (like your GW) an attacker could pick the stolen ATSHA device and put it in their own device to allow it to transmit signed messages to any node in your system until you revoke the PSK in your GW (and corresponding nodes).

    But that requires SMD-desoldering right? I guy who knows SMD + network sniffing + MYS hacking certainly will target something much bigger than my house 😉


  • Contest Winner

    @rvendrame Hehe, well, if they go for hacking you keyfob, they probably know enough to realize that desoldering is not necessary. Just tap into the programming interface of the Arduino and write your own sketch to it 😉
    However, they DO need to figure out your network topology, understand the MySensors protocol and so on. But we have to assume that is the case since we are open source. So everybody knows (or has access to) everything. The essential security here is your PSK. Your PSK must never EVER fall into the wrong hands. Either by theft or by accidental reveal (publishing it here for instance).
    As long as you keep your PSK private and make sure the nodes that has the PSK programmed in on way or another do not fall into the wrong hands, you should be OK.


  • Contest Winner

    @rvendrame Actually, I have been thinking and I think I have figured out a way to implement diversification in the signing protocol without revealing IDs over the air. I need some more time to think about it, and make an feasibility assessment on wether it is possible on the limited space available (perhaps to make it an optional feature).
    I will post an update here if I figure it out (or if I deem it to much work or simply can't be bothered 😉 )
    Anyway, the end result (if I succeed) will make it possible to revoke nodes on an ID-basis in case a node/device is lost/compromised. So if someone steals your keyfob they will have to go through quite some trouble to be able to use the device to hijack into your network (if you update your network to not accept that particular keyfob anymore).
    I'll think about it. But this weekend I have to be social, so don't expect the solution (if any) anytime soon.


  • Hero Member

    @Anticimex , thanks a lot. In the way it is currently it is very good. I was thinking about a logic of having to propose to you, but didn't conclude it yet. But definitely it would requires more memory at the gateway side at least, and a good online backup of GW eprom 😉

    Something like in the node registration to the GW. The GW would ask if the node has already a PSK --- If not, it would generate one, and send to it to the node. The node then would store the PSK into the security chip, and lock it.

    This is based on assumption the GW could handle multiple PSKs (one for each node with signing capabilities). If I understood right, your logic already controls, for every node, which one requires signing or not. It would be an extra handling on that.

    So if a node is lost --- It should be relatively simple to backlist it. But I am not sure if association with of a old node (with its own PSK already stored and locked) within a new GW (in registration mode) would be feasible, as I think you mentioned the PSK can't be retrieved anymore (at least in a easy way) at the node side... Also if somehow the GW side loses the PSK list, everything will simple brick!!!!

    Anyway, just to think about it. For now lets enjoy this nice thing called mySensors 😉 I may give a try on the security over the weekend, if family + social allows it...

    Have a great weekend


  • Contest Winner

    @rvendrame It is a possibility. However, I do recommend a different approach, because your proposal involves sending the PSK in the clear OTA which potentially could be collected by a snooping device. This opens an attack vector.
    I am more thinking in the line of hashing the calculated singature with a serial (every ATSHA has a unique serial) and then sending the salted signature to the receiver (verifier). The verifier calculates the signature on its own and then
    Option A: Looks up the sender serial in a table based on NodeId and hashes the calculated signature with a stored serial for that NodeId and compares the signatures. I like this one because it is the most "anal". It is however potentially memory demanding (or slightly more complex to setup).
    Option B: Traverses a list of stored serials and tries a signature comparison with all known serials and accepts the signature if any one signature matches. I like this a bit less because any stored serial is accepted without regard of the sender. But it is probably less memory "heavy".

    To revoke a "lost" node, one simply updates the receiver and removes the corresponding serial. A snooper will never "detect" a serial since they are never sent OTA in the clear, and also an attacker will only be able to determine the serial of the device stolen (which you hopefully revoked once you detected the theft).
    The trick is to figure out an memory and user friendly way of storing and managing the serials on every receiver.

    The more I think about it, the more I want to implement it. I hate to "know" that the solution can be attacked successfully in any conceivable way. If we ignore the issue with "lost" nodes, I have not been able to identify another attack vector (not to say there is none though).
    I welcome anyone to challenge and identify issues.



  • Hi,

    Is it possible to get a small schematics/howto for using ATSHA204 chip ? Maybe some references on the shop page for exemple.
    Maybe newbie question, but look that the best for this signing feature will be to connect Arduino with this chip. Only information is on A3, ok but I will feel more confident with some schematic for newbies 🙂


  • Contest Winner

    @lunarok well there really is not more to it. You have three pins; data (to a3 or any digital IO of your choice) power (3.3 or 5V) and GND. I suggest @tbowmo s little minimalistic board (referenced on the main page as official MySensors board) for a schematic reference.


  • Hero Member

    Nice work, thank you.

    I think I'd be pretty flattered if somebody spent the time to reverse engineer a lost keyfob and my MYS network. As far as I know, nobody realizes that I have three Van Gogh's and a 50 caret diamond in my crawlspace, so I mostly don't expect that concentrated an attack, when my windows are so easily broken anyway. 🙂

    Most people with the skills to do that already have much nicer things in their homes than I available have for them to steal (aside from those paintings and rocks).

    Seriously, it's good to have the option of being relatively more secure, in particular since it seems to be fully optional. Let me check tho - this is not going to take up any program memory (Flash) if one isn't using it, right? So there's no harm or cost/bloat if you don't need it, and some really cool additional functionality if you do.


  • Hero Member

    Hmmm.. If somebody is taking security this seriously, they might want to use a different chip (or use the whitening technique referenced in an early post in this thread): http://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html Skip back and forth in the thread.

    One odd effect of using a widely used professional chip is that in some scenarios it can make one less secure - because now you are using something which has a far higher target profile than MySensors. Put another way, the MySensors community is a small enough movement that it's not worth a lot of resources to attack it; but the widely used chip IS an attractive target, and a discovered security hole might pull in MyS "for free". Not a problem if it has no vulnerabilities of course.

    Notice Bill's concern that there may be a deliberate back door in the chip. A few years ago that might seem paranoid; by now we know that it would be unusual if certain security agencies had NOT at least considered working out a special deal with the manufacturer of a widely used chip.

    Wouldn't it be interesting if the software implementation was, in some areas, more secure than the hardware?


  • Contest Winner

    @Zeph yes, backdoors in crypto HW will always be a concern for non open designs. However, these are probably not generally known and besides, they still require physical access to the device in question. And since my recommendation is (also after whitelisting feature is implemented) that PSK is revoked if a secure node is lost, a backdoor will get you nowhere as the security protocol as such is based on an open and widely regarded secure standard. If you are really paranoid, you simply need to weigh the hard option against the soft. The hard at least in theory protects you from revealing tour secrets, but the soft does not. But the soft option gives you more insight in the mechanisms used to generate the signatures.


  • Contest Winner

    @Zeph Regarding the whitening, yes, that is probably a good idea. Currently the slimmed down ATSHA driver does not implement the SHA command, but I need it anyway since it will be used for the whitelist-feature. So I can add the random improvement to both the hard and soft backend together with the whitelist stuff. I just hope I can squeeze everything down enough. The limiting device is an Ethernet GW which I believe is the "largest" (have not evaluated MQTT though).


  • Hero Member

    @Anticimex

    Believe it or not I discussed the topic with my wife this weekend, and she asked me if each ATSHA doesn't have a unique serial... :-S

    Very good - I assume this will requires more RAM in GW (only), completely acceptable in my opinion.

    I more like your option "A" 😉

    Cheers


  • Contest Winner

    @rvendrame Your wife is perfectly right, and I have indeed starting looking into option A. It will unfortunately break compatibility with ATSHA204, but I do believe everyone will use ATSHA204A so that should be fine. I hope to be able to fit everything into flash. The signing backend constructors will be updated to take a whitelist that the "verifying" end of a node network will provide. The whitelist feature overall will be an optional #define controlled feature since it will change the message signature, so if one half of Alice and Bob use it, the other has to as well. But since it will "cost" a bit both RAM and ROM, I prefer to have that feature optional since it is not really required for a "locked" network where all nodes are inaccessible.
    And still, revoking the PSK if the network is compromised is my strong recommendation. But a "blacked-out" node will require even more effort to hack for the network to accept it.

    This feature does require you to know the serial of the transmitter and it's NodeID. The serial will never be sent OTA in clear text so it is easiest obtained during personalization (it is printed on UART then). The "soft" backend will have a "fake" serial set by the "user" who hopefully makes it unique for every node. Set either through constructor or as a #define. I have not decided yet.

    In any case, once I am done, the top post will be updated to include the whitelist option and how to use it.


  • Hero Member

    @Anticimex , amazing. I understood your concerns with transmitting the serial number over the air --- But assuming the GW only enters in '"Inclusion mode" by pressing a physical button (or via its controller request), and it lasts only 1 minute typically --- Do you still see a big risk?

    Otherwise --- On everyone new node it would require a re-flash of GW, adding the new node serial to it ? Perhaps I didn't get it in the right way...


  • Contest Winner

    @rvendrame
    Serials are static so those are a one-shot config. The node ID is not that static, but once assigned, it is persisted in the EEPROM on the node so it is static enough I believe.
    I prefer not to have any useful information sent in clear text at any point sine it is difficult to ensure that a node cannot be "enticed" to reset and retransmit data at will.
    We have to remember that secure exchange does not necessarily go through a GW. In the case of keyfob -> garage door, there is no reason to relay through a GW. The keyfob could transmit to the garage-door motor directly. So relying on "inclusion" to set up secure communications is not a dependency I want to have. Any node should be able to establish signed communication with any other node. It is just a matter of the sketch used transmit the signing requrement message itself. In the GW case, the library takes care of this, but nothing prevents a node to transmit it's signing preference directly to another node in the network (such as a garage door to an associated keyfob).
    So if we assume the garage door require signed messages, the keyfob then have to transmit it's serial at some point so the garage door can "learn it" (per your suggestion). So if the keyfob is stolen, that feature can be exploited to reset the garage door nodes whitelist. Therefore I do believe the garage door has to have a hard-coded whitelist which cannot possibly be changed without physical access to it.
    Call me anal, but better safe than sorry 😉
    And yes, this is probably all overkill...but if we go overkill..let's do it with a vengeance. After all, anyone who thinks this is unnecessary can simply choose to not use it.

    EDIT: On the topic of reflash, yes. If a receiver is to be made aware of new nodes it is expected to verify messages from, it has to be updated. But to me, that both makes sense and is desired. You never want a node to automagically start accepting messages from "unknown" nodes for whatever reason. I think a bit of convenience has to be sacrificed on that topic.



  • @Anticimex really a cool thing 👍 i just wanted to know if the rasp pi version of the mysensors will also get this ? it will be very useful when we use the raspberry pi as the gateway using pigateway serial.


  • Contest Winner

    @sharath-krishna Thanks! The software driver has no real hardware dependency so yes, that should work. You will need to patch to patch the random number generation though.
    I do not think the hardware driver really needs to be ported since a raspberry will likely not be used in an environment where it can be stolen/tampered with so extra protection of PSK and such will not really be needed.
    Sorry to say, I do not have the bandwidth to support this on all hardware. I will however encourage the community to port it anyway it likes and will support as much as I can. I will try to maintain it for Arduino and am still working with strengthening it and there are a few bugs left to iron out before it can me submitted to master.


  • Hero Member

    @rvendrame:

    • The ZWave paper you point to describes a problem implementation, not the protocol itself it seems to me:

    The root cause of this issue was lack of state validation
    in the key exchange protocol handler programmed in the Z-
    Wave door lock firmware.

    • Yes, if you lose your normal key anybody that knows to which lock it belongs can break in.
    • But, if your key has no information on to which lock it belongs to the risk is small, the same is true for a remote.

  • Plugin Developer

    @Anticimex Thanks a lot! Its a great work.
    Does signature feature supports for node to node communication (I mean without gateway)?


  • Contest Winner

    @jkandasa thanks. Yes it does. But then you (as sketch developer) is responsible for sending the internal I_REQUEST_SIGNING message to inform the other node of your nodes signing requirements. The library manages this automatically for the node2gateway (and gateway2node) but not for node2node messages since the library "does not know" anything about that.



  • @hek do you have any plan to use this logic in new version api?
    @Anticimex awesome work!


  • Admin

    @C.r.a.z.y.

    Yes, this will be part of 1.5 release.


  • Contest Winner

    Thanks guys! Glad to see that it's appreciated 🙂
    I am now working on strengthening the nonces and implementing whitelisting. I hope to be able to finish it in time for the 1.5 release.
    Voluntary testers are desired!
    I will update the first post also with more instructions on how to handle whitelisting and also update it so it reflects the more recent changes on the development branch with respect to configuration as soon has I have finished the hacking.


  • Contest Winner

    UPDATE: Thread topic post updated with a lot of stuff. Whitelisting is now "in" and explained. Various updates to the text to make a few things more clear and some code examples added to show how this ties into the updates on development branch when it comes to construction of the library class and how signing comes into play.



  • @Anticimex This really is great work!
    I have one question regarding ATSHA204A: do you know where to buy ATSHA204A-STUCZ-T? I couldn't find any supplier in Europe and even on Aliexpress, I could onlyfind the ATSHA204 in SOT23-3.


  • Admin

    @phil83

    mouser.com got it in stock, they will deliver to europe as well 🙂



  • @tbowmo Thanks for the info. I found mouser this morning as well but they charge me 20€ for shipping :-(.


  • Admin

    @phil83

    You just need to make an order big enough, then they drop the handling charge 🙂



  • Any other Europeans interested in getting some chips from mouser? I could redistribute from Germany via letter. 😉



  • hello, i'm making some mysensors board that I'll present you a bit later and I've add a place for the Atsha204 sot23-3.

    I can't find it in Europe still and I would like to know if is it possible ton connect it on pin A6 instead of pin A3. I would like to keep the A0 to A5 for the user and use A6 for Atsha204 and A7 for Atcha204 floating point. Can anyone test it for me please?

    Thank's verry much!


  • Contest Winner

    @Tibus No, you cant. A6 and A7 are analog-only pins. Also, make sure you order ATSHA204A. Not ATSHA204. ATSHA uses no "floating point". Just single wire digital interface.



  • Ok, So I've to connect it on A3 (default value in mysensor?) and let the A7 floating? The A6 is not used so? (other question : I can't use digitalWrite on A6 pin?)

    Thank's verry much for the details on ATSHA204A instead of ATSHA204. The ATSHA204A is in SOT23-3 too? so the A7 is only use inside the Atmega library?


  • Contest Winner

    @Tibus A6 and A7 are analog input pins. You can use them as such but not as digital I/O.
    ATSHA204A is identical but more feature-rich compared to ATSHA204. One added feature is a SHA256 which is required for MySensors use. ATSHA204 is discontinued by Atmel. You can connect the ATSHA to any digital I/O pin you like but you will have to patch the config if you pick anything not called "A3".



  • Ok, thank's! I've already change every A6 pin connection to A3. Can the user use A3 for analogic even if ATSHA204 is connected on it? or do I have to remove the A3 pin available for the user?


  • Contest Winner

    @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.


  • Admin

    @Anticimex

    The "analog" pins can actually be used as digital IO pins.


  • Contest Winner

    @hek Not A6 and A7. They are pure analog.


  • Admin

    Ok! That's new to me 🙂


  • Contest Winner

    @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.


  • Admin

    @hek @Anticimex

    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


  • Contest Winner

    @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 words 🙂

    I made this pic from the Datasheet giving you the pinouts of the ATSHA204A in all known housings.
    ATSHA204Apins.jpg

    And the way how to connect is (shamelessly stolen from the GW design of @Anticimex 🙂 )
    ATSHA204Aconnect.jpg


  • Contest Winner

    @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.


  • Contest Winner

    @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!


  • Contest Winner

    @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.


  • Hardware Contributor

    @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.


  • Contest Winner

    @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!


  • Hardware Contributor

    @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:

    1. Node sends data to gateway which in my case is published to MQTT
    2. some consumer likes to have this signed and sends the node the message back with a sign request
    3. 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.


  • Contest Winner

    @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.


  • Contest Winner

    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.


  • Hardware Contributor

    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?


  • Contest Winner

    @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).


  • Hardware Contributor

    @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.


  • Contest Winner

    @scalz
    Thanks and you are welcome 🙂


  • Contest Winner

    @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.


  • Hardware Contributor

    @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!


  • Contest Winner

    @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).


  • Hardware Contributor

    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.


  • Contest Winner

    @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.


  • Contest Winner

    @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.


  • Hardware Contributor

    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


  • Contest Winner

    @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?


  • Contest Winner

    @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


  • Contest Winner

    @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?



  • @Anticimex:

    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...


  • Contest Winner

    @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?


  • Contest Winner

    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.


  • Contest Winner

    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 🙂


  • Contest Winner

    First post updated to better reflect the state of the 'development' branch. Signing is currently not available on 'master'.


  • Hardware Contributor

    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

Log in to reply
 

Suggested Topics

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts