Skip to content

Instantly share code, notes, and snippets.

@darconeous
Last active September 9, 2019 21:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darconeous/76605230cd0cc8d45ff6c445a0166d1f to your computer and use it in GitHub Desktop.
Save darconeous/76605230cd0cc8d45ff6c445a0166d1f to your computer and use it in GitHub Desktop.

Mechanism for Secure-by-Default Mesh Network Communication (Draft)

Overall goal is to remove the requirement that hosts keep track of a packet counter across resets. This is a common source of implementation difficulty. When not implemented correctly, it can severely compromise the security of the network.

Symmetric-Crypto Version

In the symmetric version of this scheme, there is a single secret MASTER_KEY that all participants on the mesh network know. From this key we derive the following keys using some as-of-yet unspecified mechanism:

  • SEED_AUTH_KEY
  • SECONDARY_KEY

SECONDARY_KEY is used to generate pair-wise keys as well as a broadcast key for each device.

Each device keeps track of two values for a given boot: FRAME_COUNTER and KEY_SEED, both of which are public. Devices periodically scan for nearby peers, fetching their frame counters and key seed.

When a device wishes to communicate with a peer, it calculates the PEER_KEY to use in the following manner: The KEY_SEED of each peer is collected, sorted and concatenated in ascending order (big endian). PEER_KEY is the result of calculating the AES128-CBC-MAC of this concatenation using SECONDARY_KEY.

If a device wishes to send out a broadcast message to its peers, it calculates the BROADCAST_KEY to use in the following manner:

  • Let our key seed be KEY_SEED.
  • KEY_SEED is encrypted with SECONDARY_KEY using AES-128-ECB, yielding BROADCAST_KEY.

At every power cycle, we reset our frame counter and choose a random seed key. We then announce to our peers that our KEY_SEED has changed, and they fetch our KEY_SEED and continue.

The KEY_SEED for a peer is authenticated by a challenge-response. When a peer asks for the KEY_SEED of other peers, it includes SEED_NONCE, the length of which is the difference between the size of the block-cipher key and the size of FRAME_COUNTER. This nonce is used to generate a SEED_REQUEST_MAC (to avoid replay attacks) which is included with the response. The key used for the MAC is SEED_AUTH_KEY.

SEED_REQUEST_MAC is calculated as follows:

  • FRAME_COUNTER is appended big-endian to SEED_NONCE, yielding NONCE_FC.
  • NONCE_FC is encrypted with SEED_AUTH_KEY using AES-128-ECB, yielding MAC_X.
  • MAC_X is XORed with KEY_SEED, yielding MAC_Y.
  • MAC_Y is encrypted with SEED_AUTH_KEY using AES-128-ECB, yielding SEED_REQUEST_MAC.

Asymmetric-Crypto Version

The asymmetric-crypto version has the following benefits:

  • More secure: Unicast keys between any two peers are known only to those peers.
  • More flexible: Individual devices can also be securely ejected from the network.

This comes at a cost: it is significantly more resource intensive. At least two expensive asymmetric cryptographic operations is required for every peer we interact with. The fact that at least one asymmetric cryptographic operation would be required to identify an invalid request from an attacker could lead to denial of service attacks.

These expensive operations can be offloaded to dedicated secure elements. Luckily, such secure elements are now becoming fairly inexpensive.

In the asymmetric version of this scheme, each network has a public and private key, NET_KEY_PUB and NET_KEY_PRI. This key is used to generate "certificates" for devices that are a part of the network.

Each device on the network also has their own public/private key pair: DEVICE_KEY_PUB and DEVICE_KEY_PRI. To become a part of the mesh network, the device gives DEVICE_KEY_PUB to a commissioner, who then uses NET_KEY_PRI to generate a certificate: DEVICE_NET_CERT(This certificate also contains NET_KEY_PUB). DEVICE_NET_CERT is then given to the device, providing the device with the credentials to authenticate itself to other devices. It is not necessary (and highly discouraged) for devices on the network to know NET_KEY_PRI unless those devices are used to commission new devices onto the network.

Note that the DEVICE_NET_CERT doesn't need to be a full X.509 certificate, it could be little more than a concatenation of the NET_KEY_PUB, DEVICE_KEY_PUB, and a signature.

Devices on the mesh need to communicate with their peers individually to set up pair-wise symmetric keys as well as identify a broadcast key for each peer. An authenticated diffie hellman scheme would be used to generate a pair-wise key, and an encryption scheme suitable for the given cryptosystem can be used for broadcast key sharing.

The rough steps per peer-pair would be:

  1. Device A requests a key sync by sending Device B DEVICE_NET_CERT_A along with the public diffe-helman parameter DH_A, with a signature DH_SIG_A signed by DEVICE_KEY_PRI_A.
  2. Device B responds to the key sync request by sending Device A DEVICE_NET_CERT_B along with the public diffe-helman parameter DH_B, with a signature DH_SIG_B signed by DEVICE_KEY_PRI_A.
  3. Both sides verify each other's certificates and the signature on the diffe-helman parameter. If that all checks out, diffe-helman is used to generate a secret shared key: PEER_KEY_AB.
  4. Each side finishes the sync by sending each other their own unique broadcast key in packets encrypted with keys derived from PEER_KEY_AB.

To be continued...

@RorisangSitoboli
Copy link

Great work. Am following it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment