View Source Grizzly.ZWave.CommandClasses.S0 (grizzly v8.5.1)
S0 (Security) Command Class
Summary
Functions
Derive the S0 authentication key (for calculating MACs) from the network key.
Calculates the MAC for an S0 Message Encapsulation command.
Derive the S0 encryption key (for calculating MACs) from the network key.
Functions
@spec authentication_key(<<_::128>>) :: <<_::128>>
Derive the S0 authentication key (for calculating MACs) from the network key.
This is done by encrypting the S0 authentication vector (0x55 repeated 16 times) with the network key using AES-128-ECB.
calculate_mac(network_key, command_byte, sender_node_id, receiver_node_id, sender_nonce, receiver_nonce, encrypted_payload)
View Source@spec calculate_mac( network_key :: <<_::128>>, command_byte :: 129 | 193, sender_node_id :: pos_integer(), receiver_node_id :: pos_integer(), sender_nonce :: <<_::64>>, receiver_nonce :: <<_::64>>, encrypted_payload :: binary() ) :: <<_::64>>
Calculates the MAC for an S0 Message Encapsulation command.
First, a block of authorization data is created by concatenating the following values: the IV, the command byte (0x81 or 0xC1), the sender node ID, the receiver node ID, the length of the encrypted payload, and the encrypted payload itself.
The IV is constructed by concatenating the sender nonce (which is included in the command -- in the spec, this is the "initialization vector" field) with the receiver nonce (which was obtained via a Nonce Get/Report exchange).
Because this is unclear in the docs, it is important to note that the sequencing byte (which includes the second frame, sequenced, and sequence counter fields) is part of the encrypted payload, which is why it isn't included in the auth data block.
The auth data block is then padded to the block size (16 bytes for AES-128) and
then encrypted in 16-byte blocks using the network authentication key (see
authentication_key/1
). The IV used for the first block is 16 bytes of 0x00,
and the IV for each subsequent block is the output from the previous block.
The MAC is the first 8 bytes of the final block.
@spec encryption_key(<<_::128>>) :: <<_::128>>
Derive the S0 encryption key (for calculating MACs) from the network key.
This is done by encrypting the S0 encryption vector (0xAA repeated 16 times) with the network key using AES-128-ECB.