blob: 17cade74aacd44dd96a1471118fc6beef6cf171c [file] [log] [blame] [edit]
Thread Key Management
=====================
This document describes the key management mechanism in Thread.
Other details about Thread, such as routing protocols, will be
described in subsequent documents.
Introduction
------------
## Goals ##
* Completely decentralized.
* Fault-tolerant.
* Straightforward implementation.
Terminology
-----------
* `ThreadKey`: PSK used to grant access to the network.
* `NetworkKey`: Temporary key used to secure and authenticate traffic
on the network.
* `NetworkKeyUpdate`: A bundle of information describing the current
`NetworkKey` and associated information, such as the age of the
key, when a next rotation is scheduled to occur, and which node
created the key.
* "Network Leader": The node which submitted the currently accepted
`NetworkKey`.
* `NetworkKeyIndex`: a 24 bit value identifying a specific revision
of the `NetworkKey`.
* "Masked index": The bitwise-AND of the `NetworkKeyIndex` and
`NETWORK_KEY_INDEX_MASK`.
## Notation ##
* `x | y`: Simple concatenation of `y` after `x`.
* `UPPER_OCTETS(x, l)`: The upper (first) `l` octets of `x`.
* `LOWER_OCTETS(x, l)`: The lower (last) `l` octets of `x`.
* `H(x)`: Cryptographic hash of `x`. Assumed to be SHA256.
* `HMAC(key, x)`: HMAC of `x` using `k` as the key.
Assumed to be HMAC-SHA256.
* `HKDF-Extract(salt, ikm)`: RFC5869 HKDF Key Extraction.
* `HKDF-Expand(prk, info, l)`: RFC5869 HKDF Key Expansion.
* `HKDF(salt, info, ikm, l)`: RFC5869 HKDF Key Extraction and Expansion.
* `RANDOM_DATA(l)`: Random data `l` octets long.
* `CRYPT-CCM(nonce, key, x)`: Cryptographic encryption using CCM mode.
Assumed to use AES128. rfc3610
* `DECRYPT-CCM(nonce, key, x)`: Cryptographic encryption using CCM mode.
Assumed to use AES128. rfc3610
* `PBKDF2(PRF, Password, Salt, c, dkLen)`: RFC2898.
## Constants ##
* `AES_CCM_KEY_LENGTH`: Length of a AES-CCM key, in octets.
Defined to be `16`.
* `MAC_KEY_LENGTH`: Length of a MAC key, in octets. Value is
`AES_CCM_KEY_LENGTH` for 802.15.4.
* `HASH_LENGTH`: Length of the hash output from the `H()` function.
This is `32` for SHA256.
* `THREAD_KEY_LENGTH`: Length of the thread administrative keys. Value
is `HASH_LENGTH`. May be between `MAC_KEY_LENGTH`
and `HASH_LENGTH`. Standard length is the same as
`MAC_KEY_LENGTH`.
* `AES_CCM_M`: 8 bytes.
* `NETWORK_KEY_INDEX_MASK`: 0x7F
Functional Description
----------------------
This key management system features two classes of keys: administrative
keys (hereafter called 'Thread keys') and network keys. Each is calculated
independently and has no mathematical relationship to each other.
The thread key is used to grant access to the network,
whereas the network key is used to secure traffic on the network.
Using the thread key, you can learn the associated
network key from other devices on that network. Once a node learns
the current network key and associated network key index it may
then communicate with other nodes on the network as a peer.
Key rotation is handled automatically on a periodic basis, thus allowing
the network to operate securely without necessitating changing the key
used to grant access to the network.
## Key Classes ##
Network keys are used to secure the contents of packets and provide
confidence that whoever created a given packet also had the same
network key. Since device must have the network key in order to
participate on the network, why don’t we just have a single class of
keys?
Network keys must be rotated on a regular basis in order to retain
the security characteristics of the stream cipher (In this case,
AES-CCM) when used over a large amount of data. Thus, network keys
are ephemeral. If a device misses a key rotation, it must somehow
rediscover the current network key in order to once again be able to
participate on the network.
The thread key is used as a PSK (pre-shared secret) to enable a
node to quickly and securely discover the current network keys from
other nodes. Thread keys do not need to be regularly rotated to maintain
network security. This has a number of benefits:
* Devices which have been powered off for a long period of
time are able to quickly rejoin the network.
* Since only symmetric encryption is used, the implementation can
be small and efficient.
* The application doesn't need to concern itself with network
key rotation, as this is handled automatically.
Rotation of the thread key is not precluded, but doing so is not
necessary for the security of the MAC layer. Since the network keys
are not derived from the thread keys, the thread keys can be changed
independently of the network keys, allowing thread keys to be changed
without disrupting network connectivity.
## Initial Provisioning ##
Initial provisioning of thread keys can occur via a number of methods:
* Out-of-band provisioning, including direct entry on the device
joining the network (if possible).
* In-band via EAP tunneled over PANA, similar to how ZigBeeIP nodes
discover the network key.
* In-band via a proprietary protocol. (E.g. Weave)
## Comparison with other systems ##
Other systems, such as ZigBeeIP and ConnectIP, use different
mechanisms.
With ZigBeeIP, the joining host obtains the current network key
from the network coordinator using EAP via PANA. The PANA session
is maintained for the duration of the connection to the network.
When the network key needs to be rotated, the coordinator uses
the established PANA sessions to set the next network key. Since
thread has no coordinator, this approach will not work.
In ConnectIP, the joining host obtains the network key using a
secured DTLS exchange, authenticating the peer using a signed
certificate and private ECC key. When the network is joinable, *any*
device which has the appropriate certificate can learn the current
network key, which is concerning. Additionally, if a node misses
two network key rotations, the node has "fallen off the boat", and
must rejoin the network using manual intervention.
While this later part could be considered negavite, having a built-in
self-destruct for network-association is actually desirable for
some applications. However, instead of relying on this as a side-effect
of network key rotation (which is always necessary), it would be more
ideal if such behavior could be decoupled entirely from the network
key rotation process.
By having different classes of keys, you can disassociate such
network-association-self-destruct timing from the rotation of network
keys. For example, you could rotate the network keys every day but only
rotate the thread keys once a month. This way a device would only
"fall off the boat" when out of communication for about a month, but
would have no trouble rejoining the network without intervention if
it were turned off for a week. (There are of course many details
that I am glossing over here, which I will elaborate more on in
other sections)
Protocol Overview
-----------------
The goal of this mechanism is allow a group of homogenous nodes to
securely agree on a shared secret that periodically changes (rotation).
The system is designed to converge quickly in the presence of
inconsistencies and will attempt to always maintain network connectivity
with peers while rotating and converging.
## Network Key Updates ##
The central mechanism behind this key management system is the Network
Key Update. The Network Key Update is a bundle of information which is
broadcast in the clear to a node's immediate peers and describes either
the current state of the `NetworkKey` or a proposed future `NetworkKey`.
Network key updates are broadcast periodically, after specific events,
and upon request from another node. Network key updates, along with
requests for network key updates, are ALWAYS transmitted using link-local
broadcast. This helps the network key state converge more quickly in
cases when there is an inconsistency.
Specifically, a network key update MUST be broadcast under all of the
following conditions:
1. When a node has restarted and intends to rejoin the network.
2. When a node has adopted or staged a new network key.
3. Whenever the age of the currently staged network key passes the
T=0 threshold.
Upon responding to a broadcast request for a network key update, a node
MUST wait a randomly-determined amount of time before generating and
broadcasting the current network key update. In order to minimize
network congestion, the request for a network key update MUST be
abandoned or ignored if either of the following conditions are true:
1. While waiting during the random delay, a valid network key update
broadcast for the same key has been received from a different node.
2. The node has already broadcast a network key update within the
past five seconds.
Note that the above restrictions apply ONLY to network key update
broadcasts in response to a request.
## Network Key Update Format ##
The format of the `NetworkKeyUpdate` is as follows:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---.
| | N |
+ Network Key Origin Address (EUI-64) + O |
| | N |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ C |
| Network Key Long Index | E |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---'
| | |
+ + <'
| Encrypted Network Key |
+ +
| (AES128-CCM using key derived from ThreadKey) |
+ +
| |
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ---.
| | N |
+ Network Key MAC + O |
| | N |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ C |
| NetworkKeyAge in 1/10 seconds |Rotate Interval| E |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---'
| NetworkKeyAge MAC | |
+ + <'
| (AES128-CCM using key derived from ThreadKey) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The key age is a signed 24-bit integer which measures the age of the key
in 1/10th seconds. T=0 is the point in time at which the key becomes
valid. Negative values are used during key staging and settling,
to account for key creation race conditions.
The rotate interval is an unsigned integer which measures the expected
period of time to pass between key rotations, measured in hours. The
maximum value for this field is 232, or 9.6 days. Larger values for this
field MUST cause the entire network key update to be rejected.
Updates are authenticated via AES-CCM. In each of the two cases where
AES128-CCM is employed, all of the data
prior to the encryption is considered to be the 'header' and is included
in the authentication as such. The TTS MAC is calculated by encrypting
a zero-length message using the indicated nonce. The key used is
derived using HKDF:
HKDF-Expand( ThreadKey, "NetworkKeyUpdate", AES_CCM_KEY_LENGTH )
When receiving a network key sync update, a series of checks are
performed to determine if the update is valid and what the resulting
action should be. When a node receives a network sync update, it
can take one of the following four actions:
* Ignore it.
* Ignore it and initiate a completely new key rotation.
* Stage it and begin the settling process.
* Immediately apply it.
Which action is taken depends on the relative preference of the received
network key update and if we are currently in the middle of rotating keys.
## Network Key Update Preference ##
Key updates are accepted or ignored based on a comparison procedure.
The first step is always to compare the key indexes. If the key index of the
update is less than the current key index, the update is ALWAYS ignored.
The subsequent steps depend on if we are currently rotating keys (the
"settling period") or not.
The second step is always to compare this update to the last received update.
If they have the same key index, key origin hwaddr, and key value, then ignore
the update UNLESS it indicates an older key age than we have calculated by at
least one second.
Then, if we are currently in the middle of a key rotation:
1. If a comparison of the encrypted key contents indicates that the new update
is lexicographically later to the last received update, then ignore the new
update.
2. Verify that the update decrypts properly and is authentic. If it does not
then ignore the new update.
3. Replace the last received update with the new update, possibly leaving
the key settling period if the age of the key is zero or positive.
Or, if we are NOT currently in the middle of a key rotation:
1. If the key index is equal to our current network key index, but the key
in the update is different, ignore the update and immediately propose a new
network key for the next index.
2. Verify that the update decrypts properly and is authentic. If it does not
then ignore the new update.
3. Replace the last received update with the new update, possibly entering
a key settling period if the age of the key is negative.
## Network Key Index Mask ##
The network key index used by this protocol is much larger than the
key index field typically used in the link-layer protocols targetted
by this mechanism. A mask, `NETWORK_KEY_INDEX_MASK`, is applied to
the network key index to obtain a value appropriate to use for
such a field.
NETWORK_KEY_INDEX_MASK = 0x7F
The bitwise-AND of the `NetworkKeyLongIndex` and `NETWORK_KEY_INDEX_MASK`
is the "masked index".
## Network Key Rotation ##
Any node may manually initiate a key rotation by incrementing the
network key index, generating a new network key, and broadcasting
the network key update.
If, after incrementing `NetworkKeyLongIndex`, the bitwise-AND of
`NetworkKeyLongIndex` and `NETWORK_KEY_INDEX_MASK` (the "masked index")
is zero, the `NetworkKeyLongIndex` MUST be incremented again. Network
keys with a masked index of zero are invalid and MUST NEVER be
broadcast.
New keys are always generated with a negative age, typically between
-10 and -15 seconds. This period of time before T=0 is called the
rotation settling period. The purpose of this period is to allow
time for the network to converge to a single network key before
everyone switches over to a new key. This is important when two nodes
which are not directly in radio contact with each other propose
a new key at exactly the same moment.
### Automatic Key Rotation ###
While key rotations can be manually initiated, this is usually
unnecessary due to the automatic key rotation. Automatic key rotation
works as follows:
In order to minimize the contention for the generation of a new key,
the node which generated the most recent network key (the "leader")
is always given the first opportunity to propose a new network key
at the first expiration of the current rotation interval. If the
leader does not propose a new key before the next expected rotation,
then all nodes are free to propose new keys.
## Use of the NetworkKey ##
The network key is used to derive additional keys that are used
for securing and authenticating traffic on the network, such as
the `MACKey` and `MLEKey`.
The keys for MAC and MLE are derived from the `NetworkKey` in a way
which is compatible with the MAC/MLE key derivation in ZigBeeIP.
While additional work must be done to allow for future ZigBeeIP
compatibility, we can avoid preventing it outright by using their
MAC key derivation mechanism. The keys are derived as follows:
MACKey = UPPER_OCTETS(
HMAC(UPPER_OCTETS(NetworkKey,16), "ZigBeeIP"),
MAC_KEY_LENGTH
)
MLEKey = LOWER_OCTETS(
HMAC(UPPER_OCTETS(NetworkKey,16), "ZigBeeIP"),
MAC_KEY_LENGTH
)
## State Machine ##
The thread key management state machine is relatively simple and
is described below in pseudocode:
// We can't do anything until we are provisioned.
WAIT_UNTIL(thread_keys_are_set());
timeout_value = 5;
// Periodically request network keys while we wait to receive them.
while (!network_keys_are_set()) {
send_network_key_request();
timeout_value = timeout_value * 2;
if (timeout_value > 60)
timeout_value = 60;
WAIT_UNTIL(
seconds_have_elapsed(timeout_value)
OR network_keys_are_set()
);
}
// Normal idle state.
while (network_keys_are_set())
{
timeout_value = KEY_ROTATION_PERIOD;
if (we_are_the_thread_leader())
{
timeout_value = timeout_value * 2;
}
WAIT_UNTIL(
seconds_have_elapsed(timeout_value)
OR received_and_staged_network_key_update()
);
if (seconds_have_elapsed(timeout_value))
{
begin_and_stage_network_key_rotation();
}
/* Now enter the network key sync settling period */
if (!key_rotation_has_settled())
{
while (!key_rotation_has_settled())
{
WAIT_UNTIL(
seconds_have_elapsed(time_to_settle())
OR received_network_key_update()
);
if (!received_network_key_update())
break;
}
/* Finished key rotation settling period. */
apply_staged_network_key_update();
}
}
start_over();
The driving events of the state machine are:
* Setting of the thread key (provisioning)
* Timeouts
* Receiving network key sync updates
## Thread Key Generation ##
In cases where the thread network is created by an automated process
and will never have the need to be accessed using a user-entered
password, the `ThreadKey` may be generated using any appropriate
key generation mechanism. However, in cases where a password to the
network is desired, the following procedure MUST be used to derive
`ThreadKey`:
ThreadKey = PBKDF2(
HMAC-SHA256,
ThreadPassword,
NetworkName | NetworkXPANID,
4096,
THREAD_KEY_LENGTH
)
Security Considerations
-----------------------
### Importance of proper NetworkKey generation ###
Typical sources of entropy, including hardware random number generators,
tend to produce less than one bit of entropy per bit. As a result, the
use of the following prodecure using HKDF to derive new network keys
is STRONGLY RECOMMENDED:
NetworkKey = HKDF(
LocalHardwareAddress | NetworkKeyLongIndex,
"NetworkKey",
RANDOM_DATA(THREAD_KEY_LENGTH*2),
THREAD_KEY_LENGTH
)
### Replay attack resistance ##
Replaying network key updates, even an old one, will have no effect on the
network. Replayed packets will be ignored by all nodes that have already
received a subsequent key update.
### Tamper resistance ###
Every byte in the network key update is authenticated using AES-CCM.
An attacker who does not have the thread key would be unable to change
parameters like age or key rotation period in a way that would be accepted
by other nodes.
### Auth-counter unnecessary ###
An auth-counter is unnecessary because each node can propose no more than one
single key per key index. This makes the nonce value of the hardware address
plus the key index sufficient to secure the key.
### Key-index rollover ###
While over a long enough period of time the key index will roll over, this
is in practice not a problem. You could rotate the key every hour for half
a million years before even getting close to reusing a key index. (Note, we
may want to consider changing the key index to a 24-bit number, which would
give us nearly two-thousand years of hourly key rotations before reusing
a key index. This would give us an extra byte for "future" use).
Example Operation
-----------------
Commissioning:
Node A Node B
------ ------
| |
+-----------------------------------> |
| 802.15.4 Beacon Request |
| |
| |
| <-----------------------------------+
| 802.14.5 Beacon |
| |
: :
=== [Weave/PANA Authentication] ===
: :
| |
* ThreadKey obtained. |
| |
+-----------------------------------> |
| Bcast Network Key Update Request |
| |
| |
| <-----------------------------------+
| Bcast Network Key Update #1 |
| |
* Key update #1 accepted |
| |
+-----------------------------------> |
| Bcast Network Key Update #1 |
: :
Resuming after missing key rotations:
Node A Node B
------ ------
: |
: |
* Power On, at key #2 |
| |
+-----------------------------------> |
| Bcast Network Key Update Request |
| |
| |
| <-----------------------------------+
| Bcast Network Key Update #5 |
| |
* Key update #5 accepted |
| |
+-----------------------------------> |
| Bcast Network Key Update #5 |
: :
Two nodes resuming with out-of-sync keys:
Node A Node B
------ ------
: :
: :
* Power On, at key #2 :
| :
+-----------------------------------> :
| Bcast Network Key Update Request :
| :
| :
+-----------------------------------> :
| Bcast Network Key Update #2 :
| :
| :
| Power On, at Key #5 *
| |
| |
| <---------------------------------- |
| Bcast Network Key Update Request |
| |
| |
+-----------------------------------> |
| Bcast Network Key Update #2 |
| |
| Key update #2 ignored: too old *
| |
| <-----------------------------------+
| Bcast Network Key Update #5 |
| |
* Key update #5 accepted |
| |
+-----------------------------------> |
| Bcast Network Key Update #5 |
: :
Standard key rotation:
Node A Node B
------ ------
| |
* Using key #5 Using key #5 *
| |
: :
| |
| Generates key update #6 *
| |
| <-----------------------------------+
| Bcast Network Key Update #6 |
| |
* Key update #6 accepted |
| |
+-----------------------------------> |
| Bcast Network Key Update #6 |
| |
: :
======= [Key Settling Period] =====
: :
| |
+ <---------------------------------> +
| Bcast Network Key Update #6 |
| |
: :
Key update conflict (assume #6.c calculates as preferable to #6.a):
Node A Node B Node C
------ ------ ------
| | |
* Generates key update #6.a | |
| | |
| | |
+------------------------------> | |
| Bcast Network Key Update #6.a | Generates key update #6.c *
| | |
| Key update #6.a accepted * |
| | |
| <------------------------------+-------------------------------> |
| Bcast Network Key Update #6.a | Bcast Network Key Update #6.a |
| | |
| | Key update #6.a ignored: pref *
| | |
| | <-------------------------------+
| | Bcast Network Key Update #6.c |
| | |
| * Key update #6.c accepted |
| | |
| <------------------------------+-------------------------------> |
| Bcast Network Key Update #6.c | Bcast Network Key Update #6.c |
| | |
* Key update #6.c accepted | |
| | |
+------------------------------> | |
| Bcast Network Key Update #6.c | |
| | |
: : :
==== [Key Settling Period] === ==== [Key Settling Period] ====
: : :
| | |
+ <----------------------------> + <-----------------------------> +
| Bcast Network Key Update #6.c | Bcast Network Key Update #6.c |
| | |
: : :
Fork merging (different keys, same key index, one or both are settled):
Node A Node B
------ ------
| |
* Using #5.a Using #5.b *
| |
+-----------------------------------> |
| Bcast Network Key Update #5.a |
| |
| Key update #5.a ignored: fork *
| |
| Generates key update #6 *
| |
| <-----------------------------------+
| Bcast Network Key Update #6 |
| |
* Key update #6 accepted |
| |
+-----------------------------------> |
| Bcast Network Key Update #6 |
| |
: :
======= [Key Settling Period] =====
: :
| |
+ <---------------------------------> +
| Bcast Network Key Update #6 |
| |
: :
----------------------------------------------------------------------------
SCRATCHPAD
Overview
--------
### Justification for Key Classes ###
THIS SECTION IS A WORK IN PROGRESS.
Functional Explanation
----------------------
The current network key is encrypted the thread
key and distributed to other nodes without additional encryption.
This bundle of information is called the `NetworkKeySyncUpdate`.
Nodes wishing to join the network first broadcast a query for the
most recent `NetworkKeySyncUpdate`. Once they receive it, they can
decrypt the network key and begin participating on the network
as a peer. Key rotation is also implemented using this
structure, and is described in more detail below.
Key Rotation
============
A node with infrastructure credentials that isn't the leader may
initiate a new rotation and become the leader when it notices that
the Thread leader has missed two or more key rotations.
The network keys are synchronized using `NetworkKeySyncUpdate`s. They are
formatted as follows:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---.
| | N |
+ Network Key Origin Address (EUI-64) + O |
| | N |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ C |
| Network Key Long Index | E |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---'
| | |
+ + <'
| Encrypted Network Key |
+ +
| (AES128-CCM using key derived from ThreadKey) |
+ +
| |
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ---.
| | N |
+ Network Key MAC + O |
| | N |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ C |
| Key age in 1/10 seconds |Rotate Interval| E |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---'
| Key age/interval MAC | |
+ + <'
| (AES128-CCM using key derived from ThreadKey) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Notation
--------
Network Properties
------------------
A Thread network has the following long-term non-derived properties:
* `NetworkName`: (16 bytes) Human-readable network identifier.
UTF-8 encoded.
* `NetworkXPANID`: (8 bytes) Randomly-chosen value used for network
disambiguation. Must be changed whenever the thread
keys change.
* One of the following:
- `ThreadPassword`: (n Bytes) Key material used for deriving the
`ThreadKey`. Never directly stored
on a device on the network.
- `ThreadKey`: On networks that don't have passwords,
this key is generated directly.
Additionally, a Thread network has the following short-term non-derived
properties:
* `NetworkKeyLongIndex`: (4 Bytes) Identifies which key is being used.
Increments on key rotation.
* `NetworkKey`: Randomly generated by the 'thread leader'. All other
network keys are ultimately derived from this key.
* `ThreadLeaderHWAddr`: The hardware address of the device which last
initiated a successful key rotation.
* `NetworkKeyAge`: The age of the network key. May be negative during the settling period.
The following properties are derived from the above properties:
ThreadKey = PBKDF2(
HMAC-SHA256,
ThreadPassword,
NetworkName | NetworkXPANID,
4096,
THREAD_KEY_LENGTH
)
Of all of these properties, the following properties are required
for a device to join an already established thread network as a
host without any additional user actions:
* `NetworkName`
* `ThreadKey`
Property Propagation
--------------------
The following properties are presented in network beacons:
* `NetworkName`
* `NetworkXPANID`
These properties will be discovered via un-secured MLE:
* `NetworkKeySyncUpdate`, Which contains:
- `NetworkKeyLongIndex`
- `ThreadLeaderHWAddr`
- `NetworkKeyAge`
- `NetworkKey` (Encrypted By `ThreadKey`)
In addition to all of the above properties, a node stores these
additional properties:
* `ThreadtKey`
* `NetworkKey`
To change the administrative credentials for the network, you must
have `ThreadAdminKey`. `ThreadAdminPassword` SHOULD NOT be stored
directly by any node because it is only used indirectly thru
`ThreadAdminKey`. Whenever authentication credentials change, a new
randomly-generated `ThreadNonce` value should be chosen.
Security
========