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